@samitouri / QOSamiQemu / commits / 084feb9098

pc-bios/s390-ccw: Add per-queue notification offset for multi-queue virtio configurations

The initial support for virtio-blk-pci IPL devices used a single virt-queue, but other device types require multiple queues, and for PCI device types this also requires a per-queue notification offset. Add a PCI notify field to the VRing struct so that each queue has a unique notify offset as defined in the virtio spec. Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com> Signed-off-by: Jared Rossi <jrossi@linux.ibm.com> Reviewed-by: Eric Farman <farman@linux.ibm.com> Tested-by: Matthew Rosato <mjrosato@linux.ibm.com> Message-ID: <20260630141917.673995-4-jrossi@linux.ibm.com> Signed-off-by: Cornelia Huck <cohuck@redhat.com>

Zhuoying Cai committed Jun 30, 2026 at 10:19 UTC 084feb909808d542c789dcbbf0f1ad01350a90ce
4 files changed +26 -17
pc-bios/s390-ccw/virtio-pci.c
+23 -15
@@ -21,7 +21,6 @@ VirtioPciCap c_cap; /* Common capabilities */
21 VirtioPciCap d_cap; /* Device capabilities */
22 VirtioPciCap n_cap; /* Notify capabilities */
23 uint32_t notify_mult;
24 -uint16_t q_notify_offset;
24
25 static int virtio_pci_set_status(uint8_t status)
26 {
@@ -74,10 +73,10 @@ int virtio_pci_reset(VDev *vdev)
73 return 0;
74 }
75
77 -long virtio_pci_notify(int vq_id)
76 +long virtio_pci_notify(VRing *vr)
77 {
79 - uint32_t offset = n_cap.off + notify_mult * q_notify_offset;
80 - return vpci_bswap16_write(offset, n_cap.bar, (uint16_t) vq_id);
78 + uint32_t offset = n_cap.off + notify_mult * vr->pci_notify;
79 + return vpci_bswap16_write(offset, n_cap.bar, (uint16_t) vr->id);
80 }
81
82 /*
@@ -301,8 +300,7 @@ static int virtio_pci_read_pci_cap_config(void)
300 }
301
302 rc = vpci_read_bswap32(pos + VPCI_N_CAP_MULT, PCI_CFGBAR, &notify_mult);
304 - if (rc || vpci_read_bswap16(c_cap.off + VPCI_C_OFFSET_Q_NOFF, c_cap.bar,
305 - &q_notify_offset)) {
303 + if (rc) {
304 puts("Failed to read notification queue configuration");
305 return -EIO;
306 }
@@ -332,7 +330,6 @@ int virtio_pci_setup(VDev *vdev)
330 VRing *vr;
331 int rc;
332 uint8_t status;
335 - uint16_t vq_size;
333 int i = 0;
334
335 vdev->guessed_disk_nature = VIRTIO_GDN_NONE;
@@ -380,28 +377,39 @@ int virtio_pci_setup(VDev *vdev)
377 return -EIO;
378 }
379
383 - if (vpci_read_bswap16(VPCI_C_OFFSET_Q_SIZE, c_cap.bar, &vq_size)) {
384 - puts("Failed to read virt-queue configuration");
385 - return -EIO;
386 - }
387 -
380 /* Configure virt-queues for pci */
381 for (i = 0; i < vdev->nr_vqs; i++) {
382 + uint16_t vq_size;
383 + uint16_t vq_notify;
384 VqInfo info = {
385 .queue = (unsigned long long) virtio_get_ring_area(i),
386 .align = KVM_S390_VIRTIO_RING_ALIGN,
387 .index = i,
394 - .num = vq_size,
388 + .num = 0,
389 };
390
391 vr = &vdev->vrings[i];
398 - vring_init(vr, &info);
392
400 - if (vpci_set_selected_vq(vr->id)) {
393 + if (vpci_set_selected_vq(i)) {
394 puts("Failed to set selected virt-queue");
395 return -EIO;
396 }
397
398 + if (vpci_read_bswap16(c_cap.off + VPCI_C_OFFSET_Q_SIZE, c_cap.bar, &vq_size)) {
399 + printf("Failed to read virt-queue %d size\n", i);
400 + return -EIO;
401 + }
402 +
403 + info.num = vq_size;
404 +
405 + if (vpci_read_bswap16(c_cap.off + VPCI_C_OFFSET_Q_NOFF, c_cap.bar, &vq_notify)) {
406 + printf("Failed to read virt-queue %d notify offset\n", i);
407 + return -EIO;
408 + }
409 +
410 + vr->pci_notify = vq_notify;
411 + vring_init(vr, &info);
412 +
413 rc = set_pci_vq_addr(VPCI_C_OFFSET_Q_DESCLO, vr->desc);
414 rc |= set_pci_vq_addr(VPCI_C_OFFSET_Q_AVAILLO, vr->avail);
415 rc |= set_pci_vq_addr(VPCI_C_OFFSET_Q_USEDLO, vr->used);
pc-bios/s390-ccw/virtio-pci.h
+1 -1
@@ -64,7 +64,7 @@ typedef struct VirtioPciCap VirtioPciCap;
64
65 void virtio_pci_id2type(VDev *vdev, uint16_t device_id);
66 int virtio_pci_reset(VDev *vdev);
67 -long virtio_pci_notify(int vq_id);
67 +long virtio_pci_notify(VRing *vr);
68 int virtio_pci_setup(VDev *vdev);
69 int virtio_pci_setup_device(void);
70
pc-bios/s390-ccw/virtio.c
+1 -1
@@ -114,7 +114,7 @@ bool vring_notify(VRing *vr)
114 vr->cookie = virtio_ccw_notify(vdev.schid, vr->id, vr->cookie);
115 break;
116 case S390_IPL_TYPE_PCI:
117 - vr->cookie = virtio_pci_notify(vr->id);
117 + vr->cookie = virtio_pci_notify(vr);
118 break;
119 default:
120 return 1;
pc-bios/s390-ccw/virtio.h
+1
@@ -107,6 +107,7 @@ struct VRing {
107 VRingUsed *used;
108 long cookie;
109 int id;
110 + uint16_t pci_notify;
111 };
112 typedef struct VRing VRing;
113