[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Minios-devel] [UNIKRAFT PATCH 5/5] plat/drivers: Implement virtio 9P request and recv



This patch implements the virtio request and receive callbacks.

Signed-off-by: Cristian Banu <cristb@xxxxxxxxx>
---
 plat/drivers/virtio/virtio_9p.c | 102 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 99 insertions(+), 3 deletions(-)

diff --git a/plat/drivers/virtio/virtio_9p.c b/plat/drivers/virtio/virtio_9p.c
index 08b2eb62a273..7ccf375b7f6f 100644
--- a/plat/drivers/virtio/virtio_9p.c
+++ b/plat/drivers/virtio/virtio_9p.c
@@ -35,6 +35,9 @@
 #include <inttypes.h>
 #include <uk/alloc.h>
 #include <uk/essentials.h>
+#include <uk/sglist.h>
+#include <uk/9pdev.h>
+#include <uk/9preq.h>
 #include <uk/9pdev_trans.h>
 #include <virtio/virtio_bus.h>
 #include <virtio/virtio_9p.h>
@@ -61,6 +64,11 @@ struct virtio_9p_device {
        uint16_t hwvq_id;
        /* libuk9p associated device (NULL if the device is not in use). */
        struct uk_9pdev *p9dev;
+       /* Scatter-gather list. */
+       struct uk_sglist sg;
+       struct uk_sglist_seg sgsegs[NUM_SEGMENTS];
+       /* Spinlock protecting the sg list. */
+       spinlock_t spinlock;
 };
 
 static int virtio_9p_connect(struct uk_9pdev *p9dev,
@@ -125,7 +133,56 @@ static int virtio_9p_disconnect(struct uk_9pdev *p9dev)
 static int virtio_9p_request(struct uk_9pdev *p9dev __unused,
                             struct uk_9preq *req __unused)
 {
-       return -EOPNOTSUPP;
+       struct virtio_9p_device *dev;
+       int rc, host_notified = 0;
+       unsigned long flags;
+       size_t read_segs, write_segs;
+
+       UK_ASSERT(p9dev);
+       UK_ASSERT(req);
+       UK_ASSERT(UK_READ_ONCE(req->state) == UK_9PREQ_READY);
+
+       /*
+        * Get the request such that it won't get freed while it's
+        * used as a cookie for the virtqueue.
+        */
+       uk_9preq_get(req);
+       dev = p9dev->priv;
+       ukplat_spin_lock_irqsave(&dev->spinlock, flags);
+       uk_sglist_reset(&dev->sg);
+
+       rc = uk_sglist_append(&dev->sg, req->xmit.buf, req->xmit.size);
+       if (rc < 0) {
+               uk_pr_err(DRIVER_NAME": Failed to append to the sg list.\n");
+               goto out_irq;
+       }
+       read_segs = dev->sg.sg_nseg;
+
+       rc = uk_sglist_append(&dev->sg, req->recv.buf, req->recv.size);
+       if (rc < 0) {
+               uk_pr_err(DRIVER_NAME": Failed to append to the sg list.\n");
+               goto out_irq;
+       }
+       write_segs = dev->sg.sg_nseg - read_segs;
+
+       rc = virtqueue_buffer_enqueue(dev->vq, req, &dev->sg,
+                                     read_segs, write_segs);
+       if (likely(rc >= 0)) {
+               UK_WRITE_ONCE(req->state, UK_9PREQ_SENT);
+               virtqueue_host_notify(dev->vq);
+               host_notified = 1;
+               rc = 0;
+       }
+
+out_irq:
+       ukplat_spin_unlock_irqrestore(&dev->spinlock, flags);
+       /*
+        * Release the reference to the 9P request if it was not successfully
+        * sent.
+        */
+       if (!host_notified)
+               uk_9preq_put(req);
+       return rc;
 }
 
 static const struct uk_9pdev_trans_ops v9p_trans_ops = {
@@ -141,9 +198,45 @@ static struct uk_9pdev_trans v9p_trans = {
        .a              = NULL /* Set by the driver initialization. */
 };
 
-static int virtio_9p_recv(struct virtqueue *vq __unused, void *priv __unused)
+static int virtio_9p_recv(struct virtqueue *vq, void *priv)
 {
-       return 0;
+       struct virtio_9p_device *dev;
+       struct uk_9preq *req = NULL;
+       uint32_t len;
+       int rc = 0;
+       int handled = 0;
+
+       UK_ASSERT(vq);
+       UK_ASSERT(priv);
+
+       dev = priv;
+       UK_ASSERT(vq == dev->vq);
+
+       while (1) {
+               rc = virtqueue_buffer_dequeue(dev->vq, (void **)&req, &len);
+               if (rc < 0)
+                       break;
+               /*
+                * Notify the 9P API that this request has been successfully
+                * received, release the reference to the request.
+                */
+               uk_9preq_receive_cb(req, len);
+               uk_9preq_put(req);
+               handled = 1;
+
+               /* Break if there are no more buffers on the virtqueue. */
+               if (rc == 0)
+                       break;
+       }
+
+       /*
+        * As the virtqueue might have empty slots now, notify any threads
+        * blocked on ENOSPC errors.
+        */
+       if (handled)
+               uk_9pdev_xmit_ready(dev->p9dev);
+
+       return handled;
 }
 
 static int virtio_9p_vq_alloc(struct virtio_9p_device *d)
@@ -168,6 +261,8 @@ static int virtio_9p_vq_alloc(struct virtio_9p_device *d)
                goto exit;
        }
 
+       uk_sglist_init(&d->sg, ARRAY_SIZE(d->sgsegs), &d->sgsegs[0]);
+
        d->vq = virtio_vqueue_setup(d->vdev,
                                    d->hwvq_id,
                                    qdesc_size,
@@ -276,6 +371,7 @@ static int virtio_9p_add_dev(struct virtio_dev *vdev)
                rc = -ENOMEM;
                goto out;
        }
+       ukarch_spin_lock_init(&d->spinlock);
        d->vdev = vdev;
        virtio_9p_feature_set(d);
        rc = virtio_9p_configure(d);
-- 
2.11.0


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.