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, ¬ify_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