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

Re: [Minios-devel] [UNIKRAFT PATCH v2 06/12] plat/drivers: Configure virtio block queue



Hi Justin,


Thank you very much for the review.

There is a patch sent on the mailing list right before this series which includes the `virtio_vqueue_release` function.

[UNIKRAFT PATCH v2] plat/virtio: Release an individual virtqueue.

For v2, I think it would be better to include it in this patch series, since no one touched it.


Thanks,

Roxana

On 26.11.2019 08:46, Justin He (Arm Technology China) wrote:
Hi Roxana

-----Original Message-----
From: Minios-devel <minios-devel-bounces@xxxxxxxxxxxxxxxxxxxx> On Behalf
Of Roxana Nicolescu
Sent: Wednesday, October 30, 2019 6:46 PM
To: minios-devel@xxxxxxxxxxxxx
Cc: sharan.santhanam@xxxxxxxxx
Subject: [Minios-devel] [UNIKRAFT PATCH v2 06/12] plat/drivers: Configure
virtio block queue

This patch introduces the initialization of the virtqueue used for
communication to Backend.

Signed-off-by: Roxana Nicolescu <nicolescu.roxana1996@xxxxxxxxx>
---
  plat/drivers/include/virtio/virtio_blk.h |   6 +
  plat/drivers/virtio/virtio_blk.c         | 203 +++++++++++++++++++++++
  2 files changed, 209 insertions(+)

diff --git a/plat/drivers/include/virtio/virtio_blk.h
b/plat/drivers/include/virtio/virtio_blk.h
index 0efb5ba9..4877e404 100644
--- a/plat/drivers/include/virtio/virtio_blk.h
+++ b/plat/drivers/include/virtio/virtio_blk.h
@@ -39,6 +39,8 @@
  #include <virtio/virtio_types.h>

  /* Feature bits */
+#define VIRTIO_BLK_F_SIZE_MAX        1       /* Indicates maximum
segment size */
+#define VIRTIO_BLK_F_SEG_MAX 2       /* Indicates maximum # of
segments */
  #define VIRTIO_BLK_F_RO              5       /* Disk is read-only */
  #define VIRTIO_BLK_F_BLK_SIZE        6       /* Block size of disk is
available*/
  #define VIRTIO_BLK_F_MQ              12      /* support more than one vq
*/
@@ -46,6 +48,10 @@
  struct virtio_blk_config {
       /* The capacity (in 512-byte sectors). */
       __u64 capacity;
+     /* The maximum segment size (if VIRTIO_BLK_F_SIZE_MAX) */
+     __u32 size_max;
+     /* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */
+     __u32 seg_max;

       /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
       __u32 blk_size;
diff --git a/plat/drivers/virtio/virtio_blk.c b/plat/drivers/virtio/virtio_blk.c
index 4346104f..8da4edc3 100644
--- a/plat/drivers/virtio/virtio_blk.c
+++ b/plat/drivers/virtio/virtio_blk.c
@@ -29,6 +29,7 @@
  #include <virtio/virtio_ids.h>
  #include <uk/blkdev.h>
  #include <virtio/virtio_blk.h>
+#include <uk/sglist.h>
  #include <uk/blkdev_driver.h>

  #define DRIVER_NAME          "virtio-blk"
@@ -41,10 +42,13 @@
   *   Access Mode
   *   Sector_size;
   *   Multi-queue,
+ *   Maximum size of a segment for requests,
+ *   Maximum number of segments per request,
   **/
  #define VIRTIO_BLK_DRV_FEATURES(features) \
       (VIRTIO_FEATURES_UPDATE(features, VIRTIO_BLK_F_RO | \
       VIRTIO_BLK_F_BLK_SIZE | VIRTIO_BLK_F_MQ | \
+     VIRTIO_BLK_F_SEG_MAX | VIRTIO_BLK_F_SIZE_MAX | \

  static struct uk_alloc *a;
  static const char *drv_name = DRIVER_NAME;
@@ -64,6 +68,10 @@ struct virtio_blk_device {
       __u16    nb_queues;
       /* List of queues */
       struct   uk_blkdev_queue *qs;
+     /* Maximum number of segments for a request */
+     __u32 max_segments;
+     /* Maximum size of a segment */
+     __u32 max_size_segment;
  };

  struct uk_blkdev_queue {
@@ -76,11 +84,164 @@ struct uk_blkdev_queue {
       struct uk_alloc *a;
       /* The nr. of descriptor limit */
       uint16_t max_nb_desc;
+     /* The nr. of descriptor user configured */
+     uint16_t nb_desc;
       /* Reference to virtio_blk_device  */
       struct virtio_blk_device *vbd;
+     /* The scatter list and its associated fragments */
+     struct uk_sglist sg;
+     struct uk_sglist_seg *sgsegs;
  };


+static int virtio_blkdev_recv_done(struct virtqueue *vq, void *priv)
+{
+     struct uk_blkdev_queue *queue = NULL;
+
+     UK_ASSERT(vq && priv);
+
+     queue = (struct uk_blkdev_queue *) priv;
+
+     uk_blkdev_drv_queue_event(&queue->vbd->blkdev, queue-
lqueue_id);
+
+     return 1;
+}
+
+/**
+ * This function setup the vring infrastructure.
+ */
+static int virtio_blkdev_vqueue_setup(struct uk_blkdev_queue *queue,
+             uint16_t nr_desc)
+{
+     uint16_t max_desc;
+     struct virtqueue *vq;
+
+     UK_ASSERT(queue);
+     max_desc = queue->max_nb_desc;
+     if (unlikely(max_desc < nr_desc)) {
+             uk_pr_err("Max desc: %"__PRIu16" Requested
desc:%"__PRIu16"\n",
+                       max_desc, nr_desc);
+             return -ENOBUFS;
+     }
+
+     nr_desc = (nr_desc) ? nr_desc : max_desc;
+     uk_pr_debug("Configuring the %d descriptors\n", nr_desc);
+
+     /* Check if the descriptor is a power of 2 */
+     if (unlikely(nr_desc & (nr_desc - 1))) {
+             uk_pr_err("Expected descriptor count as a power 2\n");
+             return -EINVAL;
+     }
+
+     vq = virtio_vqueue_setup(queue->vbd->vdev, queue->lqueue_id,
nr_desc,
+                     virtio_blkdev_recv_done, a);
+     if (unlikely(PTRISERR(vq))) {
+             uk_pr_err("Failed to set up virtqueue %"__PRIu16"\n",
+                       queue->lqueue_id);
+             return PTR2ERR(vq);
+     }
+
+     queue->vq = vq;
+     vq->priv = queue;
+
+     return 0;
+}
+
+static struct uk_blkdev_queue *virtio_blkdev_queue_setup(struct
uk_blkdev *dev,
+             uint16_t queue_id,
+             uint16_t nb_desc,
+             const struct uk_blkdev_queue_conf *queue_conf)
+{
+     struct virtio_blk_device *vbdev;
+     int rc = 0;
+     struct uk_blkdev_queue *queue;
+
+     UK_ASSERT(dev != NULL);
+     UK_ASSERT(queue_conf != NULL);
+
+     vbdev = to_virtioblkdev(dev);
+     if (unlikely(queue_id >= vbdev->nb_queues)) {
+             uk_pr_err("Invalid queue_id %"__PRIu16"\n", queue_id);
+             rc = -EINVAL;
+             goto err_exit;
+     }
+
+     queue = &vbdev->qs[queue_id];
+     queue->a = queue_conf->a;
+
+     /* Init sglist */
+     queue->sgsegs = uk_malloc(queue->a,
+                     vbdev->max_segments * sizeof(*queue->sgsegs));
+     if (unlikely(!queue->sgsegs)) {
+             rc = -ENOMEM;
+             goto err_exit;
+     }
+
+     uk_sglist_init(&queue->sg, vbdev->max_segments,
+                     queue->sgsegs);
+     queue->vbd = vbdev;
+     queue->nb_desc = nb_desc;
+     queue->lqueue_id = queue_id;
+
+     /* Setup the virtqueue with the descriptor */
+     rc = virtio_blkdev_vqueue_setup(queue, nb_desc);
+     if (rc < 0) {
+             uk_pr_err("Failed to set up virtqueue %"__PRIu16": %d\n",
+                       queue_id, rc);
+             goto setup_err;
+     }
+
+exit:
+     return queue;
+setup_err:
+     uk_free(queue->a, queue->sgsegs);
+err_exit:
+     queue = ERR2PTR(rc);
+     goto exit;
+}
+
+static int virtio_blkdev_queue_release(struct uk_blkdev *dev,
+             struct uk_blkdev_queue *queue)
+{
+     struct virtio_blk_device *vbdev;
+     int rc = 0;
+
+     UK_ASSERT(dev != NULL);
+     vbdev = to_virtioblkdev(dev);
+
+     uk_free(queue->a, queue->sgsegs);
+     virtio_vqueue_release(vbdev->vdev, queue->vq, queue->a);
I can't find the definition of virtio_vqueue_release, am I missing some patches?

--
Cheers,
Justin (Jia He)


+
+     return rc;
+}
+
+static int virtio_blkdev_queue_info_get(struct uk_blkdev *dev,
+             uint16_t queue_id,
+             struct uk_blkdev_queue_info *qinfo)
+{
+     struct virtio_blk_device *vbdev = NULL;
+     struct uk_blkdev_queue *queue = NULL;
+     int rc = 0;
+
+     UK_ASSERT(dev);
+     UK_ASSERT(qinfo);
+
+     vbdev = to_virtioblkdev(dev);
+     if (unlikely(queue_id >= vbdev->nb_queues)) {
+             uk_pr_err("Invalid queue_id %"__PRIu16"\n", queue_id);
+             rc = -EINVAL;
+             goto exit;
+     }
+
+     queue = &vbdev->qs[queue_id];
+     qinfo->nb_min = queue->max_nb_desc;
+     qinfo->nb_max = queue->max_nb_desc;
+     qinfo->nb_is_power_of_two = 1;
+
+exit:
+     return rc;
+}
+
  static int virtio_blkdev_queues_alloc(struct virtio_blk_device *vbdev,
                                   const struct uk_blkdev_conf *conf)
  {
@@ -177,6 +338,8 @@ static int virtio_blkdev_feature_negotiate(struct
virtio_blk_device *vbdev)
       __sector sectors;
       __sector ssize;
       __u16 num_queues;
+     __u32 max_segments;
+     __u32 max_size_segment;
       int rc = 0;

       UK_ASSERT(vbdev);
@@ -228,13 +391,50 @@ static int virtio_blkdev_feature_negotiate(struct
virtio_blk_device *vbdev)
               }
       } else
               num_queues = 1;
+
+     if (virtio_has_features(host_features, VIRTIO_BLK_F_SEG_MAX)) {
+             bytes_to_read = virtio_config_get(vbdev->vdev,
+                     __offsetof(struct virtio_blk_config, seg_max),
+                     &max_segments,
+                     sizeof(max_segments),
+                     1);
+             if (bytes_to_read != sizeof(max_segments))  {
+                     uk_pr_err("Failed to get maximum nb of
segments\n");
+                     rc = -EAGAIN;
+                     goto exit;
+             }
+     } else
+             max_segments = 1;
+
+     /* We need extra sg elements for head (header) and tail (status). */
+     max_segments += 2;
+
+     if (virtio_has_features(host_features, VIRTIO_BLK_F_SIZE_MAX)) {
+             bytes_to_read = virtio_config_get(vbdev->vdev,
+                     __offsetof(struct virtio_blk_config, size_max),
+                     &max_size_segment,
+                     sizeof(max_size_segment),
+                     1);
+             if (bytes_to_read != sizeof(max_size_segment))  {
+                     uk_pr_err("Failed to get size max from device %d\n",
+                                     rc);
+                     rc = -EAGAIN;
+                     goto exit;
+             }
+     } else
+             max_size_segment = __PAGE_SIZE;
+
       cap->ssize = ssize;
       cap->sectors = sectors;
       cap->ioalign = sizeof(void *);
       cap->mode = (virtio_has_features(
                       host_features, VIRTIO_BLK_F_RO)) ? O_RDONLY :
O_RDWR;
+     cap->max_sectors_per_req =
+                     max_size_segment / ssize * (max_segments - 2);

       vbdev->max_vqueue_pairs = num_queues;
+     vbdev->max_segments = max_segments;
+     vbdev->max_size_segment = max_size_segment;

       /**
        * Mask out features supported by both driver and device.
@@ -257,6 +457,9 @@ static inline void virtio_blkdev_feature_set(struct
virtio_blk_device *vbdev)
  static const struct uk_blkdev_ops virtio_blkdev_ops = {
               .get_info = virtio_blkdev_get_info,
               .dev_configure = virtio_blkdev_configure,
+             .queue_get_info = virtio_blkdev_queue_info_get,
+             .queue_setup = virtio_blkdev_queue_setup,
+             .queue_release = virtio_blkdev_queue_release,
               .dev_unconfigure = virtio_blkdev_unconfigure,
  };

--
2.17.1


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium. Thank you.

_______________________________________________
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®.