diff mbox

[v8,1/7] Process all available messages in virtqueue callback

Message ID 1362782508-3166-2-git-send-email-rtivy@ti.com (mailing list archive)
State Changes Requested
Headers show

Commit Message

Tivy, Robert March 8, 2013, 10:41 p.m. UTC
Change virtqueue callback function rpmsg_recv_done() to process all
available messages instead of just one message.

Signed-off-by: Robert Tivy <rtivy@ti.com>
---
 drivers/rpmsg/virtio_rpmsg_bus.c |   97 +++++++++++++++++++++++---------------
 1 file changed, 58 insertions(+), 39 deletions(-)
diff mbox

Patch

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index f1e3239..ae92ae7 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -782,7 +782,7 @@  out:
 }
 EXPORT_SYMBOL(rpmsg_send_offchannel_raw);
 
-/* called when an rx buffer is used, and it's time to digest a message */
+/* called when an rx buffer is used, and it's time to digest a message(s) */
 static void rpmsg_recv_done(struct virtqueue *rvq)
 {
 	struct rpmsg_hdr *msg;
@@ -791,6 +791,7 @@  static void rpmsg_recv_done(struct virtqueue *rvq)
 	struct scatterlist sg;
 	struct virtproc_info *vrp = rvq->vdev->priv;
 	struct device *dev = &rvq->vdev->dev;
+	int added_buf = 0;
 	int err;
 
 	msg = virtqueue_get_buf(rvq, &len);
@@ -799,60 +800,78 @@  static void rpmsg_recv_done(struct virtqueue *rvq)
 		return;
 	}
 
-	dev_dbg(dev, "From: 0x%x, To: 0x%x, Len: %d, Flags: %d, Reserved: %d\n",
+	while (msg) {
+		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);
-	print_hex_dump(KERN_DEBUG, "rpmsg_virtio RX: ", DUMP_PREFIX_NONE, 16, 1,
+#ifdef DEBUG_VERBOSE
+		print_hex_dump(KERN_DEBUG, "rpmsg_virtio RX: ",
+					DUMP_PREFIX_NONE, 16, 1,
 					msg, sizeof(*msg) + msg->len, true);
+#endif
 
-	/*
-	 * We currently use fixed-sized buffers, so trivially sanitize
-	 * the reported payload length.
-	 */
-	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;
-	}
+		/*
+		 * We currently use fixed-sized buffers, so trivially sanitize
+		 * the reported payload length.
+		 */
+		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);
+			break;
+		}
 
-	/* use the dst addr to fetch the callback of the appropriate user */
-	mutex_lock(&vrp->endpoints_lock);
+		/*
+		 * Use the dst addr to fetch the callback of the appropriate
+		 * user.
+		 */
+		mutex_lock(&vrp->endpoints_lock);
 
-	ept = idr_find(&vrp->endpoints, msg->dst);
+		ept = idr_find(&vrp->endpoints, msg->dst);
 
-	/* let's make sure no one deallocates ept while we use it */
-	if (ept)
-		kref_get(&ept->refcount);
+		/* let's make sure no one deallocates ept while we use it */
+		if (ept)
+			kref_get(&ept->refcount);
 
-	mutex_unlock(&vrp->endpoints_lock);
+		mutex_unlock(&vrp->endpoints_lock);
 
-	if (ept) {
-		/* make sure ept->cb doesn't go away while we use it */
-		mutex_lock(&ept->cb_lock);
+		if (ept) {
+			/* make sure ept->cb doesn't go away while we use it */
+			mutex_lock(&ept->cb_lock);
 
-		if (ept->cb)
-			ept->cb(ept->rpdev, msg->data, msg->len, ept->priv,
-				msg->src);
+			if (ept->cb)
+				ept->cb(ept->rpdev, msg->data, msg->len,
+					ept->priv, msg->src);
 
-		mutex_unlock(&ept->cb_lock);
+			mutex_unlock(&ept->cb_lock);
 
-		/* farewell, ept, we don't need you anymore */
-		kref_put(&ept->refcount, __ept_release);
-	} else
-		dev_warn(dev, "msg received with no recepient\n");
+			/* farewell, ept, we don't need you anymore */
+			kref_put(&ept->refcount, __ept_release);
+		} else
+			dev_warn(dev, "msg received with no recepient\n");
 
-	/* publish the real size of the buffer */
-	sg_init_one(&sg, msg, RPMSG_BUF_SIZE);
+		/* publish the real size of the buffer */
+		sg_init_one(&sg, msg, RPMSG_BUF_SIZE);
 
-	/* add the buffer back to the remote processor's virtqueue */
-	err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, msg, GFP_KERNEL);
-	if (err < 0) {
-		dev_err(dev, "failed to add a virtqueue buffer: %d\n", err);
-		return;
+		/* add the buffer back to the remote processor's virtqueue */
+		err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, msg, GFP_KERNEL);
+		if (err < 0) {
+			dev_err(dev, "failed to add a virtqueue buffer: %d\n",
+					err);
+			break;
+		}
+
+		added_buf = 1;
+
+		msg = virtqueue_get_buf(rvq, &len);
 	}
 
-	/* tell the remote processor we added another available rx buffer */
-	virtqueue_kick(vrp->rvq);
+	if (added_buf)
+		/*
+		 * Tell the remote processor we added another available rx
+		 * buffer.
+		 */
+		virtqueue_kick(vrp->rvq);
 }
 
 /*