From: Zhuoying Cai <[email protected]> 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 <[email protected]> Signed-off-by: Jared Rossi <[email protected]> --- pc-bios/s390-ccw/virtio-pci.c | 38 +++++++++++++++++++++-------------- pc-bios/s390-ccw/virtio-pci.h | 2 +- pc-bios/s390-ccw/virtio.c | 3 ++- pc-bios/s390-ccw/virtio.h | 1 + 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/pc-bios/s390-ccw/virtio-pci.c b/pc-bios/s390-ccw/virtio-pci.c index 53bdb52e76..2c83ec4f13 100644 --- a/pc-bios/s390-ccw/virtio-pci.c +++ b/pc-bios/s390-ccw/virtio-pci.c @@ -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); diff --git a/pc-bios/s390-ccw/virtio-pci.h b/pc-bios/s390-ccw/virtio-pci.h index 90d07cb9a7..2494df1619 100644 --- a/pc-bios/s390-ccw/virtio-pci.h +++ b/pc-bios/s390-ccw/virtio-pci.h @@ -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); diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index a448dc96e2..df04479aa6 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -114,7 +114,8 @@ 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; } diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h index d32a4830ca..75ae5bdbc2 100644 --- a/pc-bios/s390-ccw/virtio.h +++ b/pc-bios/s390-ccw/virtio.h @@ -107,6 +107,7 @@ struct VRing { VRingUsed *used; long cookie; int id; + uint16_t pci_notify; }; typedef struct VRing VRing; -- 2.54.0
