|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH v2 5/5] plat/drivers: Implement virtio 9P request and recv
Reviewed-by: Costin Lupu <costin.lupu@xxxxxxxxx>
On 9/7/19 12:45 PM, Vlad-Andrei BĂDOIU (78692) wrote:
> From: Cristian Banu <cristb@xxxxxxxxx>
>
> This patch implements the virtio request and receive callbacks.
>
> Signed-off-by: Cristian Banu <cristb@xxxxxxxxx>
> ---
> plat/drivers/virtio/virtio_9p.c | 161 +++++++++++++++++++++++++++++++-
> 1 file changed, 156 insertions(+), 5 deletions(-)
>
> diff --git a/plat/drivers/virtio/virtio_9p.c b/plat/drivers/virtio/virtio_9p.c
> index 8094ec70..fe0d69ab 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 and the vq. */
> + spinlock_t spinlock;
> };
>
> static int virtio_9p_connect(struct uk_9pdev *p9dev,
> @@ -120,10 +128,96 @@ static int virtio_9p_disconnect(struct uk_9pdev *p9dev)
> return 0;
> }
>
> -static int virtio_9p_request(struct uk_9pdev *p9dev __unused,
> - struct uk_9preq *req __unused)
> +static int virtio_9p_request(struct uk_9pdev *p9dev,
> + struct uk_9preq *req)
> {
> - return -EOPNOTSUPP;
> + struct virtio_9p_device *dev;
> + int rc, host_notified = 0;
> + unsigned long flags;
> + size_t read_segs, write_segs;
> + bool failed = false;
> +
> + 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) {
> + failed = true;
> + goto out_unlock;
> + }
> +
> + if (req->xmit.zc_buf) {
> + rc = uk_sglist_append(&dev->sg, req->xmit.zc_buf,
> + req->xmit.zc_size);
> + if (rc < 0) {
> + failed = true;
> + goto out_unlock;
> + }
> + }
> +
> + read_segs = dev->sg.sg_nseg;
> +
> + rc = uk_sglist_append(&dev->sg, req->recv.buf, req->recv.size);
> + if (rc < 0) {
> + failed = true;
> + goto out_unlock;
> + }
> +
> + if (req->recv.zc_buf) {
> + uint32_t recv_size = req->recv.size + req->recv.zc_size;
> +
> + rc = uk_sglist_append(&dev->sg, req->recv.zc_buf,
> + req->recv.zc_size);
> + if (rc < 0) {
> + failed = true;
> + goto out_unlock;
> + }
> +
> + /* Make eure there is sufficient space for Rerror replies. */
> + if (recv_size < UK_9P_RERROR_MAXSIZE) {
> + uint32_t leftover = UK_9P_RERROR_MAXSIZE - recv_size;
> +
> + rc = uk_sglist_append(&dev->sg,
> + req->recv.buf + recv_size, leftover);
> + if (rc < 0) {
> + failed = true;
> + goto out_unlock;
> + }
> + }
> + }
> +
> + 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_unlock:
> + if (failed)
> + uk_pr_err(DRIVER_NAME": Failed to append to the sg list.\n");
> + 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 = {
> @@ -138,9 +232,63 @@ 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) {
> + /*
> + * Protect against data races with virtio_9p_request() calls
> + * which are trying to enqueue to the same vq.
> + */
> + ukarch_spin_lock(&dev->spinlock);
> + rc = virtqueue_buffer_dequeue(dev->vq, (void **)&req, &len);
> + ukarch_spin_unlock(&dev->spinlock);
> + 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);
> +
> + /*
> + * Check for Rerror messages, fixup the error message if
> + * needed.
> + */
> + if (req->recv.type == UK_9P_RERROR) {
> + memcpy(req->recv.buf + req->recv.zc_offset,
> + req->recv.zc_buf,
> + MIN(req->recv.zc_size, len - UK_9P_HEADER_SIZE));
> + }
> +
> + 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_notify(dev->p9dev);
> +
> + return handled;
> }
>
> static int virtio_9p_vq_alloc(struct virtio_9p_device *d)
> @@ -165,6 +313,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,
> @@ -272,6 +422,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);
>
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |