Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328/* SPDX-License-Identifier: BSD-3-Clause *//* * Remote processor messaging * * Copyright (C) 2011 Texas Instruments, Inc. * Copyright (C) 2011 Google, Inc. * All rights reserved. */
#ifndef _LINUX_RPMSG_H#define _LINUX_RPMSG_H
#include <linux/types.h>#include <linux/device.h>#include <linux/err.h>#include <linux/device-id/rpmsg.h>#include <linux/kref.h>#include <linux/mutex.h>#include <linux/poll.h>#include <linux/rpmsg/byteorder.h>#include <uapi/linux/rpmsg.h>
struct rpmsg_device;struct rpmsg_endpoint;struct rpmsg_device_ops;struct rpmsg_endpoint_ops;
/** * struct rpmsg_channel_info - channel info representation * @name: name of service * @src: local address * @dst: destination address */struct rpmsg_channel_info { char name[RPMSG_NAME_SIZE]; u32 src; u32 dst;};
/** * rpmsg_device - device that belong to the rpmsg bus * @dev: the device struct * @id: device id (used to match between rpmsg drivers and devices) * @src: local address * @dst: destination address * @ept: the rpmsg endpoint of this channel * @announce: if set, rpmsg will announce the creation/removal of this channel * @little_endian: True if transport is using little endian byte representation */struct rpmsg_device { struct device dev; struct rpmsg_device_id id; u32 src; u32 dst; struct rpmsg_endpoint *ept; bool announce; bool little_endian;
const struct rpmsg_device_ops *ops;};
typedef int (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);typedef int (*rpmsg_flowcontrol_cb_t)(struct rpmsg_device *, void *, bool);
/** * struct rpmsg_endpoint - binds a local rpmsg address to its user * @rpdev: rpmsg channel device * @refcount: when this drops to zero, the ept is deallocated * @cb: rx callback handler * @flow_cb: remote flow control callback handler * @cb_lock: must be taken before accessing/changing @cb * @addr: local rpmsg address * @priv: private data for the driver's use * * In essence, an rpmsg endpoint represents a listener on the rpmsg bus, as * it binds an rpmsg address with an rx callback handler. * * Simple rpmsg drivers shouldn't use this struct directly, because * things just work: every rpmsg driver provides an rx callback upon * registering to the bus, and that callback is then bound to its rpmsg * address when the driver is probed. When relevant inbound messages arrive * (i.e. messages which their dst address equals to the src address of * the rpmsg channel), the driver's handler is invoked to process it. * * More complicated drivers though, that do need to allocate additional rpmsg * addresses, and bind them to different rx callbacks, must explicitly * create additional endpoints by themselves (see rpmsg_create_ept()). */struct rpmsg_endpoint { struct rpmsg_device *rpdev; struct kref refcount; rpmsg_rx_cb_t cb; rpmsg_flowcontrol_cb_t flow_cb; struct mutex cb_lock; u32 addr; void *priv;
const struct rpmsg_endpoint_ops *ops;};
/** * struct rpmsg_driver - rpmsg driver struct * @drv: underlying device driver * @id_table: rpmsg ids serviced by this driver * @probe: invoked when a matching rpmsg channel (i.e. device) is found * @remove: invoked when the rpmsg channel is removed * @callback: invoked when an inbound message is received on the channel * @flowcontrol: invoked when remote side flow control request is received */struct rpmsg_driver { struct device_driver drv; const struct rpmsg_device_id *id_table; int (*probe)(struct rpmsg_device *dev); void (*remove)(struct rpmsg_device *dev); int (*callback)(struct rpmsg_device *, void *, int, void *, u32); int (*flowcontrol)(struct rpmsg_device *, void *, bool);};
static inline u16 rpmsg16_to_cpu(struct rpmsg_device *rpdev, __rpmsg16 val){ if (!rpdev) return __rpmsg16_to_cpu(rpmsg_is_little_endian(), val); else return __rpmsg16_to_cpu(rpdev->little_endian, val);}
static inline __rpmsg16 cpu_to_rpmsg16(struct rpmsg_device *rpdev, u16 val){ if (!rpdev) return __cpu_to_rpmsg16(rpmsg_is_little_endian(), val); else return __cpu_to_rpmsg16(rpdev->little_endian, val);}
static inline u32 rpmsg32_to_cpu(struct rpmsg_device *rpdev, __rpmsg32 val){ if (!rpdev) return __rpmsg32_to_cpu(rpmsg_is_little_endian(), val); else return __rpmsg32_to_cpu(rpdev->little_endian, val);}
static inline __rpmsg32 cpu_to_rpmsg32(struct rpmsg_device *rpdev, u32 val){ if (!rpdev) return __cpu_to_rpmsg32(rpmsg_is_little_endian(), val); else return __cpu_to_rpmsg32(rpdev->little_endian, val);}
static inline u64 rpmsg64_to_cpu(struct rpmsg_device *rpdev, __rpmsg64 val){ if (!rpdev) return __rpmsg64_to_cpu(rpmsg_is_little_endian(), val); else return __rpmsg64_to_cpu(rpdev->little_endian, val);}
static inline __rpmsg64 cpu_to_rpmsg64(struct rpmsg_device *rpdev, u64 val){ if (!rpdev) return __cpu_to_rpmsg64(rpmsg_is_little_endian(), val); else return __cpu_to_rpmsg64(rpdev->little_endian, val);}
#if IS_ENABLED(CONFIG_RPMSG)
int rpmsg_register_device_override(struct rpmsg_device *rpdev, const char *driver_override);int rpmsg_register_device(struct rpmsg_device *rpdev);int rpmsg_unregister_device(struct device *parent, struct rpmsg_channel_info *chinfo);int __register_rpmsg_driver(struct rpmsg_driver *drv, struct module *owner);void unregister_rpmsg_driver(struct rpmsg_driver *drv);void rpmsg_destroy_ept(struct rpmsg_endpoint *);struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *, rpmsg_rx_cb_t cb, void *priv, struct rpmsg_channel_info chinfo);
int rpmsg_send(struct rpmsg_endpoint *ept, const void *data, int len);int rpmsg_sendto(struct rpmsg_endpoint *ept, const void *data, int len, u32 dst);
int rpmsg_trysend(struct rpmsg_endpoint *ept, const void *data, int len);int rpmsg_trysendto(struct rpmsg_endpoint *ept, const void *data, int len, u32 dst);
__poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp, poll_table *wait);
ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept);
int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool pause, u32 dst);
#else
static inline int rpmsg_register_device_override(struct rpmsg_device *rpdev, const char *driver_override){ return -ENXIO;}
static inline int rpmsg_register_device(struct rpmsg_device *rpdev){ return -ENXIO;}
static inline int rpmsg_unregister_device(struct device *parent, struct rpmsg_channel_info *chinfo){ /* This shouldn't be possible */ WARN_ON(1);
return -ENXIO;}
static inline int __register_rpmsg_driver(struct rpmsg_driver *drv, struct module *owner){ /* This shouldn't be possible */ WARN_ON(1);
return -ENXIO;}
static inline void unregister_rpmsg_driver(struct rpmsg_driver *drv){ /* This shouldn't be possible */ WARN_ON(1);}
static inline void rpmsg_destroy_ept(struct rpmsg_endpoint *ept){ /* This shouldn't be possible */ WARN_ON(1);}
static inline struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev, rpmsg_rx_cb_t cb, void *priv, struct rpmsg_channel_info chinfo){ /* This shouldn't be possible */ WARN_ON(1);
return NULL;}
static inline int rpmsg_send(struct rpmsg_endpoint *ept, const void *data, int len){ /* This shouldn't be possible */ WARN_ON(1);
return -ENXIO;}
static inline int rpmsg_sendto(struct rpmsg_endpoint *ept, const void *data, int len, u32 dst){ /* This shouldn't be possible */ WARN_ON(1);
return -ENXIO;
}
static inline int rpmsg_trysend(struct rpmsg_endpoint *ept, const void *data, int len){ /* This shouldn't be possible */ WARN_ON(1);
return -ENXIO;}
static inline int rpmsg_trysendto(struct rpmsg_endpoint *ept, const void *data, int len, u32 dst){ /* This shouldn't be possible */ WARN_ON(1);
return -ENXIO;}
static inline __poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp, poll_table *wait){ /* This shouldn't be possible */ WARN_ON(1);
return 0;}
static inline ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept){ /* This shouldn't be possible */ WARN_ON(1);
return -ENXIO;}
static inline int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool pause, u32 dst){ /* This shouldn't be possible */ WARN_ON(1);
return -ENXIO;}
#endif /* IS_ENABLED(CONFIG_RPMSG) */
/* use a macro to avoid include chaining to get THIS_MODULE */#define register_rpmsg_driver(drv) \ __register_rpmsg_driver(drv, THIS_MODULE)
/** * module_rpmsg_driver() - Helper macro for registering an rpmsg driver * @__rpmsg_driver: rpmsg_driver struct * * Helper macro for rpmsg drivers which do not do anything special in module * init/exit. This eliminates a lot of boilerplate. Each module may only * use this macro once, and calling it replaces module_init() and module_exit() */#define module_rpmsg_driver(__rpmsg_driver) \ module_driver(__rpmsg_driver, register_rpmsg_driver, \ unregister_rpmsg_driver)
#endif /* _LINUX_RPMSG_H */