[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |