Merge tag 'firewire-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee139...
[cascardo/linux.git] / drivers / rpmsg / virtio_rpmsg_bus.c
index a59684b..b6135d4 100644 (file)
@@ -757,14 +757,14 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
        mutex_lock(&vrp->tx_lock);
 
        /* add message to the remote processor's virtqueue */
-       err = virtqueue_add_buf(vrp->svq, &sg, 1, 0, msg, GFP_KERNEL);
+       err = virtqueue_add_outbuf(vrp->svq, &sg, 1, msg, GFP_KERNEL);
        if (err) {
                /*
                 * need to reclaim the buffer here, otherwise it's lost
                 * (memory won't leak, but rpmsg won't use it again for TX).
                 * this will wait for a buffer management overhaul.
                 */
-               dev_err(dev, "virtqueue_add_buf failed: %d\n", err);
+               dev_err(dev, "virtqueue_add_outbuf failed: %d\n", err);
                goto out;
        }
 
@@ -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 */
@@ -839,14 +829,45 @@ static void rpmsg_recv_done(struct virtqueue *rvq)
        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);
+       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);
 }
 
 /*
@@ -951,8 +972,10 @@ static int rpmsg_probe(struct virtio_device *vdev)
        bufs_va = dma_alloc_coherent(vdev->dev.parent->parent,
                                RPMSG_TOTAL_BUF_SPACE,
                                &vrp->bufs_dma, GFP_KERNEL);
-       if (!bufs_va)
+       if (!bufs_va) {
+               err = -ENOMEM;
                goto vqs_del;
+       }
 
        dev_dbg(&vdev->dev, "buffers: va %p, dma 0x%llx\n", bufs_va,
                                        (unsigned long long)vrp->bufs_dma);
@@ -970,7 +993,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
 
                sg_init_one(&sg, cpu_addr, RPMSG_BUF_SIZE);
 
-               err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, cpu_addr,
+               err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, cpu_addr,
                                                                GFP_KERNEL);
                WARN_ON(err); /* sanity check; this can't really happen */
        }