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

[Minios-devel] [UNIKRAFT PATCH v2 07/16] plat/xen/drivers/blk: Configure blkfront queue



Blkfront queues use Xen shared rings.
This patch introduces the allocation and initialization of the shared
ring, and also adds the event-handler for queue notification.

Signed-off-by: Roxana Nicolescu <nicolescu.roxana1996@xxxxxxxxx>
---
 plat/xen/drivers/blk/blkfront.c | 126 ++++++++++++++++++++++++++++++++++++++++
 plat/xen/drivers/blk/blkfront.h |  11 ++++
 2 files changed, 137 insertions(+)

diff --git a/plat/xen/drivers/blk/blkfront.c b/plat/xen/drivers/blk/blkfront.c
index a2dbf825..44828f0f 100644
--- a/plat/xen/drivers/blk/blkfront.c
+++ b/plat/xen/drivers/blk/blkfront.c
@@ -55,6 +55,129 @@
 static struct uk_alloc *drv_allocator;
 
 
+static int blkfront_ring_init(struct uk_blkdev_queue *queue)
+{
+       struct blkif_sring *sring = NULL;
+       struct blkfront_dev *dev;
+
+       UK_ASSERT(queue);
+       dev = queue->dev;
+       sring = uk_malloc_page(queue->a);
+       if (!sring)
+               return -ENOMEM;
+
+       memset(sring, 0, PAGE_SIZE);
+       SHARED_RING_INIT(sring);
+       FRONT_RING_INIT(&queue->ring, sring, PAGE_SIZE);
+
+       queue->ring_ref = gnttab_grant_access(dev->xendev->otherend_id,
+                       virt_to_mfn(sring), 0);
+       UK_ASSERT(queue->ring_ref != GRANT_INVALID_REF);
+
+       return 0;
+}
+
+static void blkfront_ring_fini(struct uk_blkdev_queue *queue)
+{
+       int rc;
+
+       if (queue->ring_ref != GRANT_INVALID_REF) {
+               rc = gnttab_end_access(queue->ring_ref);
+               UK_ASSERT(rc);
+       }
+
+       if (queue->ring.sring != NULL)
+               uk_free_page(queue->a, queue->ring.sring);
+}
+
+/* Handler for event channel notifications */
+static void blkfront_handler(evtchn_port_t port __unused,
+               struct __regs *regs __unused, void *arg)
+{
+       struct uk_blkdev_queue *queue;
+
+       UK_ASSERT(arg);
+       queue = (struct uk_blkdev_queue *)arg;
+       uk_blkdev_drv_queue_event(&queue->dev->blkdev, queue->queue_id);
+}
+
+static struct uk_blkdev_queue *blkfront_queue_setup(struct uk_blkdev *blkdev,
+               uint16_t queue_id,
+               uint16_t nb_desc __unused,
+               const struct uk_blkdev_queue_conf *queue_conf)
+{
+       struct blkfront_dev *dev;
+       struct uk_blkdev_queue *queue;
+       int err = 0;
+
+       UK_ASSERT(blkdev != NULL);
+
+       dev = to_blkfront(blkdev);
+       if (queue_id >= dev->nb_queues) {
+               uk_pr_err("Invalid queue identifier: %"__PRIu16"\n", queue_id);
+               return ERR2PTR(-EINVAL);
+       }
+
+       queue = &dev->queues[queue_id];
+       queue->a = queue_conf->a;
+       queue->queue_id = queue_id;
+       queue->dev = dev;
+       err = blkfront_ring_init(queue);
+       if (err) {
+               uk_pr_err("Failed to init ring: %d.\n", err);
+               return ERR2PTR(err);
+       }
+
+       err = evtchn_alloc_unbound(dev->xendev->otherend_id,
+                       blkfront_handler, queue,
+                       &queue->evtchn);
+       if (err) {
+               uk_pr_err("Failed to create event-channel: %d.\n", err);
+               err *= -1;
+               goto err_out;
+       }
+
+       return queue;
+
+err_out:
+       blkfront_ring_fini(queue);
+       uk_free(drv_allocator, queue);
+       return ERR2PTR(err);
+}
+
+static int blkfront_queue_release(struct uk_blkdev *blkdev,
+               struct uk_blkdev_queue *queue)
+{
+       UK_ASSERT(blkdev != NULL);
+       UK_ASSERT(queue != NULL);
+
+       mask_evtchn(queue->evtchn);
+       unbind_evtchn(queue->evtchn);
+       blkfront_ring_fini(queue);
+
+       return 0;
+}
+
+static int blkfront_queue_get_info(struct uk_blkdev *blkdev,
+               uint16_t queue_id,
+               struct uk_blkdev_queue_info *qinfo)
+{
+       struct blkfront_dev *dev;
+
+       UK_ASSERT(blkdev);
+       UK_ASSERT(qinfo);
+
+       dev = to_blkfront(blkdev);
+       if (queue_id >= dev->nb_queues) {
+               uk_pr_err("Invalid queue identifier: %"__PRIu16"\n", queue_id);
+               return -EINVAL;
+       }
+
+       qinfo->nb_is_power_of_two = 1;
+
+       return 0;
+}
+
 static int blkfront_configure(struct uk_blkdev *blkdev,
                const struct uk_blkdev_conf *conf)
 {
@@ -117,6 +240,9 @@ static void blkfront_get_info(struct uk_blkdev *blkdev,
 static const struct uk_blkdev_ops blkfront_ops = {
        .get_info = blkfront_get_info,
        .dev_configure = blkfront_configure,
+       .queue_get_info = blkfront_queue_get_info,
+       .queue_setup = blkfront_queue_setup,
+       .queue_release = blkfront_queue_release,
        .dev_unconfigure = blkfront_unconfigure,
 };
 
diff --git a/plat/xen/drivers/blk/blkfront.h b/plat/xen/drivers/blk/blkfront.h
index 553a1117..656f7845 100644
--- a/plat/xen/drivers/blk/blkfront.h
+++ b/plat/xen/drivers/blk/blkfront.h
@@ -43,10 +43,21 @@
  */
 #include <uk/blkdev.h>
 
+#include <xen/io/blkif.h>
+#include <common/gnttab.h>
+#include <common/events.h>
+
+
 /*
  * Structure used to describe a queue used for both requests and responses
  */
 struct uk_blkdev_queue {
+       /* Front_ring structure */
+       struct blkif_front_ring ring;
+       /* Grant ref pointing at the front ring. */
+       grant_ref_t ring_ref;
+       /* Event channel for the front ring. */
+       evtchn_port_t evtchn;
        /* Allocator for this queue. */
        struct uk_alloc *a;
        /* The libukblkdev queue identifier */
-- 
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®.