@@ -776,7 +776,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;
@@ -785,6 +785,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);
@@ -793,60 +794,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 recipient\n");
+ /* farewell, ept, we don't need you anymore */
+ kref_put(&ept->refcount, __ept_release);
+ } else
+ dev_warn(dev, "msg received with no recipient\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);
}
/*
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(-)