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