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@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
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@seabios.org Cc: stefanha@redhat.com; Liu, Changpeng changpeng.liu@intel.com; Harris, James R james.r.harris@intel.com; Zedlewski, Piotr piotr.zedlewski@intel.com; marcandre.lureau@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@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