summaryrefslogtreecommitdiffstats
path: root/drivers/rpmsg/virtio_rpmsg_bus.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-07 14:02:00 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-07 14:02:00 -0700
commit3e11a00d8561622a2598254853e2e8cc3e51e544 (patch)
tree2517e2497c53173f733975e4f5d617fd85b79cb0 /drivers/rpmsg/virtio_rpmsg_bus.c
parentc807b17375be26d7710b248deae6d75ecb32e4ba (diff)
parent397944df3290ddc46dcc6a08cd71fb560700431b (diff)
downloadlinux-3e11a00d8561622a2598254853e2e8cc3e51e544.tar.bz2
Merge tag 'rpmsg-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/ohad/rpmsg
Pull rpmsg changes from Ohad Ben-Cohen: "A small pull request consisting of: - Make rpmsg process all pending messages instead of just one, from Robert Tivy - Fix Kconfig dependency on VIRTUALIZATION, from Suman. Note: this was submitted late during the 3.9 rc cycle and it seemed appropriate to wait with it for the merge window. - Belated addition of an rpmsg entry to the MAINTAINERS file. People seem to look for this" * tag 'rpmsg-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/ohad/rpmsg: rpmsg: fix kconfig dependencies for VIRTIO MAINTAINERS: add rpmsg entry rpmsg: process _all_ pending messages in rpmsg_recv_done
Diffstat (limited to 'drivers/rpmsg/virtio_rpmsg_bus.c')
-rw-r--r--drivers/rpmsg/virtio_rpmsg_bus.c49
1 files changed, 35 insertions, 14 deletions
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 56fceafec9ec..b6135d4d54eb 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);
}
/*