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

Re: [Minios-devel] [UNIKRAFT PATCH 8/9] plat/xen/drivers/9p: Implement request and recv



Reviewed-by: Costin Lupu <costin.lupu@xxxxxxxxx>

On 9/7/19 1:21 PM, Vlad-Andrei BĂDOIU (78692) wrote:
> From: Cristian Banu <cristb@xxxxxxxxx>
> 
> This patch implement request and receive functions for the xen 9P
> transport driver.
> 
> Signed-off-by: Cristian Banu <cristb@xxxxxxxxx>
> ---
>  plat/xen/drivers/9p/9pfront.c | 138 +++++++++++++++++++++++++++++++++-
>  1 file changed, 134 insertions(+), 4 deletions(-)
> 
> diff --git a/plat/xen/drivers/9p/9pfront.c b/plat/xen/drivers/9p/9pfront.c
> index 1a8b49c5..a5321898 100644
> --- a/plat/xen/drivers/9p/9pfront.c
> +++ b/plat/xen/drivers/9p/9pfront.c
> @@ -37,6 +37,7 @@
>  #include <uk/alloc.h>
>  #include <uk/assert.h>
>  #include <uk/essentials.h>
> +#include <uk/errptr.h>
>  #include <uk/list.h>
>  #include <uk/9pdev.h>
>  #include <uk/9preq.h>
> @@ -54,10 +55,96 @@ static struct uk_alloc *a;
>  static UK_LIST_HEAD(p9front_device_list);
>  static DEFINE_SPINLOCK(p9front_device_list_lock);
>  
> -static void p9front_handler(evtchn_port_t evtchn __unused,
> +struct p9front_header {
> +     uint32_t size;
> +     uint8_t type;
> +     uint16_t tag;
> +} __packed;
> +
> +static void p9front_recv(struct p9front_dev_ring *ring)
> +{
> +     struct p9front_dev *p9fdev = ring->dev;
> +     evtchn_port_t evtchn = ring->evtchn;
> +     RING_IDX cons, prod, masked_cons, masked_prod;
> +     int ring_size, rc;
> +     struct p9front_header hdr;
> +     struct uk_9preq *req;
> +     uint32_t buf_cnt, zc_buf_cnt;
> +
> +     ring_size = XEN_FLEX_RING_SIZE(p9fdev->ring_order);
> +
> +     while (1) {
> +             cons = ring->intf->in_cons;
> +             prod = ring->intf->in_prod;
> +             xen_rmb();
> +
> +             if (xen_9pfs_queued(prod, cons, ring_size) < sizeof(hdr)) {
> +                     notify_remote_via_evtchn(evtchn);
> +                     return;
> +             }
> +
> +             masked_prod = xen_9pfs_mask(prod, ring_size);
> +             masked_cons = xen_9pfs_mask(cons, ring_size);
> +
> +             xen_9pfs_read_packet(&hdr, ring->data.in, sizeof(hdr),
> +                             masked_prod, &masked_cons, ring_size);
> +
> +             req = uk_9pdev_req_lookup(p9fdev->p9dev, hdr.tag);
> +             if (PTRISERR(req)) {
> +                     uk_pr_warn("Found invalid tag=%u\n", hdr.tag);
> +                     cons += hdr.size;
> +                     xen_mb();
> +                     ring->intf->in_cons = cons;
> +                     continue;
> +             }
> +
> +             masked_cons = xen_9pfs_mask(cons, ring_size);
> +
> +             /*
> +              * Compute amount of data to read into request buffer and into
> +              * zero-copy buffer.
> +              */
> +             buf_cnt = hdr.size;
> +             if (hdr.type != UK_9P_RERROR && req->recv.zc_buf)
> +                     buf_cnt = MIN(buf_cnt, req->recv.zc_offset);
> +             zc_buf_cnt = hdr.size - buf_cnt;
> +
> +             xen_9pfs_read_packet(req->recv.buf, ring->data.in, buf_cnt,
> +                             masked_prod, &masked_cons, ring_size);
> +             xen_9pfs_read_packet(req->recv.zc_buf, ring->data.in,
> +                             zc_buf_cnt, masked_prod, &masked_cons,
> +                             ring_size);
> +             cons += hdr.size;
> +             xen_mb();
> +             ring->intf->in_cons = cons;
> +
> +             rc = uk_9preq_receive_cb(req, hdr.size);
> +             if (rc)
> +                     uk_pr_warn("Could not receive reply: %d\n", rc);
> +
> +             /* Release reference held by uk_9pdev_req_lookup(). */
> +             uk_9preq_put(req);
> +     }
> +}
> +
> +static void p9front_handler(evtchn_port_t evtchn,
>                           struct __regs *regs __unused,
> -                         void *arg __unused)
> +                         void *arg)
>  {
> +     struct p9front_dev_ring *ring = arg;
> +
> +     UK_ASSERT(ring);
> +     UK_ASSERT(ring->evtchn == evtchn);
> +
> +     /*
> +      * A new interrupt means that there is a response to be received, which
> +      * means that a previously sent request has been removed from the out
> +      * ring. Thus, the API can be notified of the possibility of retrying to
> +      * send requests blocked on ENOSPC errors.
> +      */
> +     if (ring->dev->p9dev)
> +             uk_9pdev_xmit_notify(ring->dev->p9dev);
> +     p9front_recv(ring);
>  }
>  
>  static void p9front_free_dev_ring(struct p9front_dev *p9fdev, int idx)
> @@ -242,9 +329,52 @@ static int p9front_disconnect(struct uk_9pdev *p9dev 
> __unused)
>       return 0;
>  }
>  
> -static int p9front_request(struct uk_9pdev *p9dev __unused,
> -                        struct uk_9preq *req __unused)
> +static int p9front_request(struct uk_9pdev *p9dev,
> +                        struct uk_9preq *req)
>  {
> +     struct p9front_dev *p9fdev;
> +     struct p9front_dev_ring *ring;
> +     int ring_idx, ring_size;
> +     RING_IDX masked_prod, masked_cons, prod, cons;
> +
> +     UK_ASSERT(p9dev);
> +     UK_ASSERT(req);
> +     UK_ASSERT(req->state == UK_9PREQ_READY);
> +
> +     p9fdev = p9dev->priv;
> +
> +     ring_size = XEN_FLEX_RING_SIZE(p9fdev->ring_order);
> +
> +     ring_idx = req->tag % p9fdev->nb_rings;
> +     ring = &p9fdev->rings[ring_idx];
> +
> +     /* Protect against concurrent writes to the out ring. */
> +     ukarch_spin_lock(&ring->spinlock);
> +     cons = ring->intf->out_cons;
> +     prod = ring->intf->out_prod;
> +     xen_mb();
> +
> +     masked_prod = xen_9pfs_mask(prod, ring_size);
> +     masked_cons = xen_9pfs_mask(cons, ring_size);
> +
> +     if (ring_size - xen_9pfs_queued(prod, cons, ring_size) <
> +                     req->xmit.size + req->xmit.zc_size) {
> +             ukarch_spin_unlock(&ring->spinlock);
> +             return -ENOSPC;
> +     }
> +
> +     xen_9pfs_write_packet(ring->data.out, req->xmit.buf, req->xmit.size,
> +                           &masked_prod, masked_cons, ring_size);
> +     xen_9pfs_write_packet(ring->data.out, req->xmit.zc_buf, 
> req->xmit.zc_size,
> +                           &masked_prod, masked_cons, ring_size);
> +     req->state = UK_9PREQ_SENT;
> +     xen_wmb();
> +     prod += req->xmit.size + req->xmit.zc_size;
> +     ring->intf->out_prod = prod;
> +
> +     ukarch_spin_unlock(&ring->spinlock);
> +     notify_remote_via_evtchn(ring->evtchn);
> +
>       return 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®.