// SPDX-License-Identifier: GPL-2.0 /* * Virtio-based remote processor messaging bus * * Copyright (C) 2011 Texas Instruments, Inc. * Copyright (C) 2011 Google, Inc. * * Ohad Ben-Cohen <[email protected]> * Brian Swetland <[email protected]> */ #define pr_fmt(fmt) … #include <linux/dma-mapping.h> #include <linux/idr.h> #include <linux/jiffies.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/rpmsg.h> #include <linux/rpmsg/byteorder.h> #include <linux/rpmsg/ns.h> #include <linux/scatterlist.h> #include <linux/slab.h> #include <linux/sched.h> #include <linux/virtio.h> #include <linux/virtio_ids.h> #include <linux/virtio_config.h> #include <linux/wait.h> #include "rpmsg_internal.h" /** * struct virtproc_info - virtual remote processor state * @vdev: the virtio device * @rvq: rx virtqueue * @svq: tx virtqueue * @rbufs: kernel address of rx buffers * @sbufs: kernel address of tx buffers * @num_bufs: total number of buffers for rx and tx * @buf_size: size of one rx or tx buffer * @last_sbuf: index of last tx buffer used * @bufs_dma: dma base addr of the buffers * @tx_lock: protects svq, sbufs and sleepers, to allow concurrent senders. * sending a message might require waking up a dozing remote * processor, which involves sleeping, hence the mutex. * @endpoints: idr of local endpoints, allows fast retrieval * @endpoints_lock: lock of the endpoints set * @sendq: wait queue of sending contexts waiting for a tx buffers * @sleepers: number of senders that are waiting for a tx buffer * * This structure stores the rpmsg state of a given virtio remote processor * device (there might be several virtio proc devices for each physical * remote processor). */ struct virtproc_info { … }; /* The feature bitmap for virtio rpmsg */ #define VIRTIO_RPMSG_F_NS … /** * struct rpmsg_hdr - common header for all rpmsg messages * @src: source address * @dst: destination address * @reserved: reserved for future use * @len: length of payload (in bytes) * @flags: message flags * @data: @len bytes of message payload data * * Every message sent(/received) on the rpmsg bus begins with this header. */ struct rpmsg_hdr { … } __packed; /** * struct virtio_rpmsg_channel - rpmsg channel descriptor * @rpdev: the rpmsg channel device * @vrp: the virtio remote processor device this channel belongs to * * This structure stores the channel that links the rpmsg device to the virtio * remote processor device. */ struct virtio_rpmsg_channel { … }; #define to_virtio_rpmsg_channel(_rpdev) … /* * We're allocating buffers of 512 bytes each for communications. The * number of buffers will be computed from the number of buffers supported * by the vring, upto a maximum of 512 buffers (256 in each direction). * * Each buffer will have 16 bytes for the msg header and 496 bytes for * the payload. * * This will utilize a maximum total space of 256KB for the buffers. * * We might also want to add support for user-provided buffers in time. * This will allow bigger buffer size flexibility, and can also be used * to achieve zero-copy messaging. * * Note that these numbers are purely a decision of this driver - we * can change this without changing anything in the firmware of the remote * processor. */ #define MAX_RPMSG_NUM_BUFS … #define MAX_RPMSG_BUF_SIZE … /* * Local addresses are dynamically allocated on-demand. * We do not dynamically assign addresses from the low 1024 range, * in order to reserve that address range for predefined services. */ #define RPMSG_RESERVED_ADDRESSES … static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept); static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len); static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst); static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, void *data, int len); static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len); static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst); static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, void *data, int len); static ssize_t virtio_rpmsg_get_mtu(struct rpmsg_endpoint *ept); static struct rpmsg_device *__rpmsg_create_channel(struct virtproc_info *vrp, struct rpmsg_channel_info *chinfo); static const struct rpmsg_endpoint_ops virtio_endpoint_ops = …; /** * rpmsg_sg_init - initialize scatterlist according to cpu address location * @sg: scatterlist to fill * @cpu_addr: virtual address of the buffer * @len: buffer length * * An internal function filling scatterlist according to virtual address * location (in vmalloc or in kernel). */ static void rpmsg_sg_init(struct scatterlist *sg, void *cpu_addr, unsigned int len) { … } /** * __ept_release() - deallocate an rpmsg endpoint * @kref: the ept's reference count * * This function deallocates an ept, and is invoked when its @kref refcount * drops to zero. * * Never invoke this function directly! */ static void __ept_release(struct kref *kref) { … } /* for more info, see below documentation of rpmsg_create_ept() */ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp, struct rpmsg_device *rpdev, rpmsg_rx_cb_t cb, void *priv, u32 addr) { … } static struct rpmsg_device *virtio_rpmsg_create_channel(struct rpmsg_device *rpdev, struct rpmsg_channel_info *chinfo) { … } static int virtio_rpmsg_release_channel(struct rpmsg_device *rpdev, struct rpmsg_channel_info *chinfo) { … } static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev, rpmsg_rx_cb_t cb, void *priv, struct rpmsg_channel_info chinfo) { … } /** * __rpmsg_destroy_ept() - destroy an existing rpmsg endpoint * @vrp: virtproc which owns this ept * @ept: endpoing to destroy * * An internal function which destroy an ept without assuming it is * bound to an rpmsg channel. This is needed for handling the internal * name service endpoint, which isn't bound to an rpmsg channel. * See also __rpmsg_create_ept(). */ static void __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept) { … } static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept) { … } static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev) { … } static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev) { … } static const struct rpmsg_device_ops virtio_rpmsg_ops = …; static void virtio_rpmsg_release_device(struct device *dev) { … } /* * create an rpmsg channel using its name and address info. * this function will be used to create both static and dynamic * channels. */ static struct rpmsg_device *__rpmsg_create_channel(struct virtproc_info *vrp, struct rpmsg_channel_info *chinfo) { … } /* super simple buffer "allocator" that is just enough for now */ static void *get_a_tx_buf(struct virtproc_info *vrp) { … } /** * rpmsg_upref_sleepers() - enable "tx-complete" interrupts, if needed * @vrp: virtual remote processor state * * This function is called before a sender is blocked, waiting for * a tx buffer to become available. * * If we already have blocking senders, this function merely increases * the "sleepers" reference count, and exits. * * Otherwise, if this is the first sender to block, we also enable * virtio's tx callbacks, so we'd be immediately notified when a tx * buffer is consumed (we rely on virtio's tx callback in order * to wake up sleeping senders as soon as a tx buffer is used by the * remote processor). */ static void rpmsg_upref_sleepers(struct virtproc_info *vrp) { … } /** * rpmsg_downref_sleepers() - disable "tx-complete" interrupts, if needed * @vrp: virtual remote processor state * * This function is called after a sender, that waited for a tx buffer * to become available, is unblocked. * * If we still have blocking senders, this function merely decreases * the "sleepers" reference count, and exits. * * Otherwise, if there are no more blocking senders, we also disable * virtio's tx callbacks, to avoid the overhead incurred with handling * those (now redundant) interrupts. */ static void rpmsg_downref_sleepers(struct virtproc_info *vrp) { … } /** * rpmsg_send_offchannel_raw() - send a message across to the remote processor * @rpdev: the rpmsg channel * @src: source address * @dst: destination address * @data: payload of message * @len: length of payload * @wait: indicates whether caller should block in case no TX buffers available * * This function is the base implementation for all of the rpmsg sending API. * * It will send @data of length @len to @dst, and say it's from @src. The * message will be sent to the remote processor which the @rpdev channel * belongs to. * * The message is sent using one of the TX buffers that are available for * communication with this remote processor. * * If @wait is true, the caller will be blocked until either a TX buffer is * available, or 15 seconds elapses (we don't want callers to * sleep indefinitely due to misbehaving remote processors), and in that * case -ERESTARTSYS is returned. The number '15' itself was picked * arbitrarily; there's little point in asking drivers to provide a timeout * value themselves. * * Otherwise, if @wait is false, and there are no TX buffers available, * the function will immediately fail, and -ENOMEM will be returned. * * Normally drivers shouldn't use this function directly; instead, drivers * should use the appropriate rpmsg_{try}send{to, _offchannel} API * (see include/linux/rpmsg.h). * * Return: 0 on success and an appropriate error value on failure. */ static int rpmsg_send_offchannel_raw(struct rpmsg_device *rpdev, u32 src, u32 dst, void *data, int len, bool wait) { … } static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) { … } static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) { … } static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, void *data, int len) { … } static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len) { … } static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) { … } static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, void *data, int len) { … } static ssize_t virtio_rpmsg_get_mtu(struct rpmsg_endpoint *ept) { … } static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev, struct rpmsg_hdr *msg, unsigned int len) { … } /* called when an rx buffer is used, and it's time to digest a message */ static void rpmsg_recv_done(struct virtqueue *rvq) { … } /* * This is invoked whenever the remote processor completed processing * a TX msg we just sent it, and the buffer is put back to the used ring. * * Normally, though, we suppress this "tx complete" interrupt in order to * avoid the incurred overhead. */ static void rpmsg_xmit_done(struct virtqueue *svq) { … } /* * Called to expose to user a /dev/rpmsg_ctrlX interface allowing to * create endpoint-to-endpoint communication without associated RPMsg channel. * The endpoints are rattached to the ctrldev RPMsg device. */ static struct rpmsg_device *rpmsg_virtio_add_ctrl_dev(struct virtio_device *vdev) { … } static void rpmsg_virtio_del_ctrl_dev(struct rpmsg_device *rpdev_ctrl) { … } static int rpmsg_probe(struct virtio_device *vdev) { … } static int rpmsg_remove_device(struct device *dev, void *data) { … } static void rpmsg_remove(struct virtio_device *vdev) { … } static struct virtio_device_id id_table[] = …; static unsigned int features[] = …; static struct virtio_driver virtio_ipc_driver = …; static int __init rpmsg_init(void) { … } subsys_initcall(rpmsg_init); static void __exit rpmsg_fini(void) { … } module_exit(rpmsg_fini); MODULE_DEVICE_TABLE(virtio, id_table); MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …;