diff options
-rw-r--r-- | MAINTAINERS | 8 | ||||
-rw-r--r-- | drivers/rpmsg/Kconfig | 1 | ||||
-rw-r--r-- | drivers/rpmsg/virtio_rpmsg_bus.c | 49 |
3 files changed, 44 insertions, 14 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index eeae5a7bdb8..e73c374483c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6716,6 +6716,14 @@ F: drivers/remoteproc/ F: Documentation/remoteproc.txt F: include/linux/remoteproc.h +REMOTE PROCESSOR MESSAGING (RPMSG) SUBSYSTEM +M: Ohad Ben-Cohen <ohad@wizery.com> +T: git git://git.kernel.org/pub/scm/linux/kernel/git/ohad/rpmsg.git +S: Maintained +F: drivers/rpmsg/ +F: Documentation/rpmsg.txt +F: include/linux/rpmsg.h + RFKILL M: Johannes Berg <johannes@sipsolutions.net> L: linux-wireless@vger.kernel.org diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig index f6e0ea6ffda..69a21938758 100644 --- a/drivers/rpmsg/Kconfig +++ b/drivers/rpmsg/Kconfig @@ -4,5 +4,6 @@ menu "Rpmsg drivers" config RPMSG tristate select VIRTIO + select VIRTUALIZATION endmenu diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 56fceafec9e..b6135d4d54e 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -776,23 +776,13 @@ out: } EXPORT_SYMBOL(rpmsg_send_offchannel_raw); -/* called when an rx buffer is used, and it's time to digest a message */ -static void rpmsg_recv_done(struct virtqueue *rvq) +static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev, + struct rpmsg_hdr *msg, unsigned int len) { - struct rpmsg_hdr *msg; - unsigned int len; struct rpmsg_endpoint *ept; struct scatterlist sg; - struct virtproc_info *vrp = rvq->vdev->priv; - struct device *dev = &rvq->vdev->dev; int err; - msg = virtqueue_get_buf(rvq, &len); - if (!msg) { - dev_err(dev, "uhm, incoming signal, but no used buffer ?\n"); - return; - } - dev_dbg(dev, "From: 0x%x, To: 0x%x, Len: %d, Flags: %d, Reserved: %d\n", msg->src, msg->dst, msg->len, msg->flags, msg->reserved); @@ -806,7 +796,7 @@ static void rpmsg_recv_done(struct virtqueue *rvq) if (len > RPMSG_BUF_SIZE || msg->len > (len - sizeof(struct rpmsg_hdr))) { dev_warn(dev, "inbound msg too big: (%d, %d)\n", len, msg->len); - return; + return -EINVAL; } /* use the dst addr to fetch the callback of the appropriate user */ @@ -842,11 +832,42 @@ static void rpmsg_recv_done(struct virtqueue *rvq) err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, msg, GFP_KERNEL); if (err < 0) { dev_err(dev, "failed to add a virtqueue buffer: %d\n", err); + return err; + } + + return 0; +} + +/* called when an rx buffer is used, and it's time to digest a message */ +static void rpmsg_recv_done(struct virtqueue *rvq) +{ + struct virtproc_info *vrp = rvq->vdev->priv; + struct device *dev = &rvq->vdev->dev; + struct rpmsg_hdr *msg; + unsigned int len, msgs_received = 0; + int err; + + msg = virtqueue_get_buf(rvq, &len); + if (!msg) { + dev_err(dev, "uhm, incoming signal, but no used buffer ?\n"); return; } + while (msg) { + err = rpmsg_recv_single(vrp, dev, msg, len); + if (err) + break; + + msgs_received++; + + msg = virtqueue_get_buf(rvq, &len); + }; + + dev_dbg(dev, "Received %u messages\n", msgs_received); + /* tell the remote processor we added another available rx buffer */ - virtqueue_kick(vrp->rvq); + if (msgs_received) + virtqueue_kick(vrp->rvq); } /* |