[SeaBIOS] [PATCH] virtio-blk/scsi: enable multi-queues support when starting device

Liu, Changpeng changpeng.liu at intel.com
Wed Sep 26 10:16:35 CEST 2018


I posted the patch again, because I didn't get any response since several months ago... :).

> -----Original Message-----
> From: Liu, Changpeng
> Sent: Wednesday, September 26, 2018 4:24 PM
> To: seabios at seabios.org
> Cc: stefanha at redhat.com; Liu, Changpeng <changpeng.liu at intel.com>; Harris,
> James R <james.r.harris at intel.com>; Zedlewski, Piotr
> <piotr.zedlewski at intel.com>; marcandre.lureau at redhat.com
> Subject: [PATCH] virtio-blk/scsi: enable multi-queues support when starting
> device
> 
> QEMU will not start all the queues since commit fb20fbb76
> "vhost: avoid to start/stop virtqueue which is not read",
> because seabios only use one queue when starting, this will
> not work for some vhost slave targets which expect the exact
> number of queues defined in virtio-pci configuration space,
> while here, we also enable those queues in the BIOS phase.
> 
> Signed-off-by: Changpeng Liu <changpeng.liu at intel.com>
> ---
>  src/hw/virtio-blk.c  | 26 +++++++++++++++++++-------
>  src/hw/virtio-ring.h |  1 +
>  src/hw/virtio-scsi.c | 28 +++++++++++++++++++---------
>  3 files changed, 39 insertions(+), 16 deletions(-)
> 
> diff --git a/src/hw/virtio-blk.c b/src/hw/virtio-blk.c
> index 88d7e54..79638ec 100644
> --- a/src/hw/virtio-blk.c
> +++ b/src/hw/virtio-blk.c
> @@ -25,7 +25,7 @@
> 
>  struct virtiodrive_s {
>      struct drive_s drive;
> -    struct vring_virtqueue *vq;
> +    struct vring_virtqueue *vq[MAX_NUM_QUEUES];
>      struct vp_device vp;
>  };
> 
> @@ -34,7 +34,7 @@ virtio_blk_op(struct disk_op_s *op, int write)
>  {
>      struct virtiodrive_s *vdrive =
>          container_of(op->drive_fl, struct virtiodrive_s, drive);
> -    struct vring_virtqueue *vq = vdrive->vq;
> +    struct vring_virtqueue *vq = vdrive->vq[0];
>      struct virtio_blk_outhdr hdr = {
>          .type = write ? VIRTIO_BLK_T_OUT : VIRTIO_BLK_T_IN,
>          .ioprio = 0,
> @@ -96,6 +96,7 @@ virtio_blk_process_op(struct disk_op_s *op)
>  static void
>  init_virtio_blk(void *data)
>  {
> +    u32 i, num_queues = 1;
>      struct pci_device *pci = data;
>      u8 status = VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER;
>      dprintf(1, "found virtio-blk at %pP\n", pci);
> @@ -109,10 +110,6 @@ init_virtio_blk(void *data)
>      vdrive->drive.cntl_id = pci->bdf;
> 
>      vp_init_simple(&vdrive->vp, pci);
> -    if (vp_find_vq(&vdrive->vp, 0, &vdrive->vq) < 0 ) {
> -        dprintf(1, "fail to find vq for virtio-blk %pP\n", pci);
> -        goto fail;
> -    }
> 
>      if (vdrive->vp.use_modern) {
>          struct vp_device *vp = &vdrive->vp;
> @@ -156,6 +153,11 @@ init_virtio_blk(void *data)
>              vp_read(&vp->device, struct virtio_blk_config, heads);
>          vdrive->drive.pchs.sector =
>              vp_read(&vp->device, struct virtio_blk_config, sectors);
> +
> +        num_queues = vp_read(&vp->common, virtio_pci_common_cfg,
> num_queues);
> +        if (num_queues < 1 || num_queues > MAX_NUM_QUEUES) {
> +             num_queues = 1;
> +        }
>      } else {
>          struct virtio_blk_config cfg;
>          vp_get_legacy(&vdrive->vp, 0, &cfg, sizeof(cfg));
> @@ -178,6 +180,13 @@ init_virtio_blk(void *data)
>          vdrive->drive.pchs.sector = cfg.sectors;
>      }
> 
> +    for (i = 0; i < num_queues; i++) {
> +        if (vp_find_vq(&vdrive->vp, i, &vdrive->vq[i]) < 0 ) {
> +            dprintf(1, "fail to find vq %u for virtio-blk %pP\n", i, pci);
> +            goto fail_vq;
> +        }
> +    }
> +
>      char *desc = znprintf(MAXDESCSIZE, "Virtio disk PCI:%pP", pci);
>      boot_add_hd(&vdrive->drive, desc, bootprio_find_pci_device(pci));
> 
> @@ -185,9 +194,12 @@ init_virtio_blk(void *data)
>      vp_set_status(&vdrive->vp, status);
>      return;
> 
> +fail_vq:
> +    for (i = 0; i < num_queues; i++) {
> +        free(vdrive->vq[i]);
> +    }
>  fail:
>      vp_reset(&vdrive->vp);
> -    free(vdrive->vq);
>      free(vdrive);
>  }
> 
> diff --git a/src/hw/virtio-ring.h b/src/hw/virtio-ring.h
> index 8604a01..3c8a2d1 100644
> --- a/src/hw/virtio-ring.h
> +++ b/src/hw/virtio-ring.h
> @@ -21,6 +21,7 @@
>  #define VIRTIO_F_IOMMU_PLATFORM         33
> 
>  #define MAX_QUEUE_NUM      (128)
> +#define MAX_NUM_QUEUES     (128)
> 
>  #define VRING_DESC_F_NEXT  1
>  #define VRING_DESC_F_WRITE 2
> diff --git a/src/hw/virtio-scsi.c b/src/hw/virtio-scsi.c
> index a87cad8..d08643f 100644
> --- a/src/hw/virtio-scsi.c
> +++ b/src/hw/virtio-scsi.c
> @@ -148,9 +148,10 @@ virtio_scsi_scan_target(struct pci_device *pci, struct
> vp_device *vp,
>  static void
>  init_virtio_scsi(void *data)
>  {
> +    u32 i, num_queues = 3;
>      struct pci_device *pci = data;
>      dprintf(1, "found virtio-scsi at %pP\n", pci);
> -    struct vring_virtqueue *vq = NULL;
> +    struct vring_virtqueue *vq[MAX_NUM_QUEUES];
>      struct vp_device *vp = malloc_high(sizeof(*vp));
>      if (!vp) {
>          warn_noalloc();
> @@ -175,29 +176,38 @@ init_virtio_scsi(void *data)
>              dprintf(1, "device didn't accept features: %pP\n", pci);
>              goto fail;
>          }
> +
> +	num_queues = vp_read(&vp->common, virtio_pci_common_cfg,
> num_queues);
> +        if (num_queues < 3 || num_queues > MAX_NUM_QUEUES) {
> +             num_queues = 3;
> +        }
>      }
> 
> -    if (vp_find_vq(vp, 2, &vq) < 0 ) {
> -        dprintf(1, "fail to find vq for virtio-scsi %pP\n", pci);
> -        goto fail;
> +    for (i = 0; i < num_queues; i++) {
> +        if (vp_find_vq(vp, i, &vq[i]) < 0 ) {
> +            dprintf(1, "fail to find vq %u for virtio-scsi %pP\n", i, pci);
> +            goto fail;
> +        }
>      }
> 
>      status |= VIRTIO_CONFIG_S_DRIVER_OK;
>      vp_set_status(vp, status);
> 
> -    int i, tot;
> +    int tot;
>      for (tot = 0, i = 0; i < 256; i++)
> -        tot += virtio_scsi_scan_target(pci, vp, vq, i);
> +        tot += virtio_scsi_scan_target(pci, vp, vq[2], i);
> 
>      if (!tot)
> -        goto fail;
> +        goto fail_vq;
> 
>      return;
> -
> +fail_vq:
> +    for (i = 0; i < num_queues; i++) {
> +        free(vq[i]);
> +    }
>  fail:
>      vp_reset(vp);
>      free(vp);
> -    free(vq);
>  }
> 
>  void
> --
> 1.9.3




More information about the SeaBIOS mailing list