mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:17 +00:00
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>
This commit is contained in:
committed by
Cornelia Huck
parent
730173107a
commit
084feb9098
@@ -21,7 +21,6 @@ VirtioPciCap c_cap; /* Common capabilities */
|
||||
VirtioPciCap d_cap; /* Device capabilities */
|
||||
VirtioPciCap n_cap; /* Notify capabilities */
|
||||
uint32_t notify_mult;
|
||||
uint16_t q_notify_offset;
|
||||
|
||||
static int virtio_pci_set_status(uint8_t status)
|
||||
{
|
||||
@@ -74,10 +73,10 @@ int virtio_pci_reset(VDev *vdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
long virtio_pci_notify(int vq_id)
|
||||
long virtio_pci_notify(VRing *vr)
|
||||
{
|
||||
uint32_t offset = n_cap.off + notify_mult * q_notify_offset;
|
||||
return vpci_bswap16_write(offset, n_cap.bar, (uint16_t) vq_id);
|
||||
uint32_t offset = n_cap.off + notify_mult * vr->pci_notify;
|
||||
return vpci_bswap16_write(offset, n_cap.bar, (uint16_t) vr->id);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -301,8 +300,7 @@ static int virtio_pci_read_pci_cap_config(void)
|
||||
}
|
||||
|
||||
rc = vpci_read_bswap32(pos + VPCI_N_CAP_MULT, PCI_CFGBAR, ¬ify_mult);
|
||||
if (rc || vpci_read_bswap16(c_cap.off + VPCI_C_OFFSET_Q_NOFF, c_cap.bar,
|
||||
&q_notify_offset)) {
|
||||
if (rc) {
|
||||
puts("Failed to read notification queue configuration");
|
||||
return -EIO;
|
||||
}
|
||||
@@ -332,7 +330,6 @@ int virtio_pci_setup(VDev *vdev)
|
||||
VRing *vr;
|
||||
int rc;
|
||||
uint8_t status;
|
||||
uint16_t vq_size;
|
||||
int i = 0;
|
||||
|
||||
vdev->guessed_disk_nature = VIRTIO_GDN_NONE;
|
||||
@@ -380,28 +377,39 @@ int virtio_pci_setup(VDev *vdev)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (vpci_read_bswap16(VPCI_C_OFFSET_Q_SIZE, c_cap.bar, &vq_size)) {
|
||||
puts("Failed to read virt-queue configuration");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Configure virt-queues for pci */
|
||||
for (i = 0; i < vdev->nr_vqs; i++) {
|
||||
uint16_t vq_size;
|
||||
uint16_t vq_notify;
|
||||
VqInfo info = {
|
||||
.queue = (unsigned long long) virtio_get_ring_area(i),
|
||||
.align = KVM_S390_VIRTIO_RING_ALIGN,
|
||||
.index = i,
|
||||
.num = vq_size,
|
||||
.num = 0,
|
||||
};
|
||||
|
||||
vr = &vdev->vrings[i];
|
||||
vring_init(vr, &info);
|
||||
|
||||
if (vpci_set_selected_vq(vr->id)) {
|
||||
if (vpci_set_selected_vq(i)) {
|
||||
puts("Failed to set selected virt-queue");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (vpci_read_bswap16(c_cap.off + VPCI_C_OFFSET_Q_SIZE, c_cap.bar, &vq_size)) {
|
||||
printf("Failed to read virt-queue %d size\n", i);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
info.num = vq_size;
|
||||
|
||||
if (vpci_read_bswap16(c_cap.off + VPCI_C_OFFSET_Q_NOFF, c_cap.bar, &vq_notify)) {
|
||||
printf("Failed to read virt-queue %d notify offset\n", i);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
vr->pci_notify = vq_notify;
|
||||
vring_init(vr, &info);
|
||||
|
||||
rc = set_pci_vq_addr(VPCI_C_OFFSET_Q_DESCLO, vr->desc);
|
||||
rc |= set_pci_vq_addr(VPCI_C_OFFSET_Q_AVAILLO, vr->avail);
|
||||
rc |= set_pci_vq_addr(VPCI_C_OFFSET_Q_USEDLO, vr->used);
|
||||
|
||||
@@ -64,7 +64,7 @@ typedef struct VirtioPciCap VirtioPciCap;
|
||||
|
||||
void virtio_pci_id2type(VDev *vdev, uint16_t device_id);
|
||||
int virtio_pci_reset(VDev *vdev);
|
||||
long virtio_pci_notify(int vq_id);
|
||||
long virtio_pci_notify(VRing *vr);
|
||||
int virtio_pci_setup(VDev *vdev);
|
||||
int virtio_pci_setup_device(void);
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ bool vring_notify(VRing *vr)
|
||||
vr->cookie = virtio_ccw_notify(vdev.schid, vr->id, vr->cookie);
|
||||
break;
|
||||
case S390_IPL_TYPE_PCI:
|
||||
vr->cookie = virtio_pci_notify(vr->id);
|
||||
vr->cookie = virtio_pci_notify(vr);
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
|
||||
@@ -107,6 +107,7 @@ struct VRing {
|
||||
VRingUsed *used;
|
||||
long cookie;
|
||||
int id;
|
||||
uint16_t pci_notify;
|
||||
};
|
||||
typedef struct VRing VRing;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user