On 5/8/26 1:23 PM, Eric Farman wrote:
On Mon, 2026-05-04 at 18:16 -0400, [email protected] wrote:
From: Jared Rossi <[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.  Also re-select the target queue before writing buffers to
ensure the proper queue is active.
Why is this patch 2/5, when the series is n/6?
The short answer is I goofed it up.  The contents of the patch are as intended.
It should be 2/6.


Signed-off-by: Jared Rossi <[email protected]>
---
  pc-bios/s390-ccw/virtio-pci.c | 36 ++++++++++++++++++++++-------------
  pc-bios/s390-ccw/virtio-pci.h |  3 ++-
  pc-bios/s390-ccw/virtio.c     |  4 +++-
  pc-bios/s390-ccw/virtio.h     |  1 +
  4 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/pc-bios/s390-ccw/virtio-pci.c b/pc-bios/s390-ccw/virtio-pci.c
index 53bdb52e76..736869f4f5 100644
--- a/pc-bios/s390-ccw/virtio-pci.c
+++ b/pc-bios/s390-ccw/virtio-pci.c
@@ -74,10 +74,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);
You no longer need the q_notify_offset variable nor the read into it.
(Ah, Joy already pointed this out; nice!)

  }
/*
@@ -166,7 +166,7 @@ int vpci_read_flex(uint64_t offset, uint8_t pcias, void 
*buf, int len)
      return 0;
  }
-static int vpci_set_selected_vq(uint16_t queue_num)
+int vpci_set_selected_vq(uint16_t queue_num)
  {
      return vpci_bswap16_write(c_cap.off + VPCI_C_OFFSET_Q_SELECT, c_cap.bar, 
queue_num);
  }
@@ -332,7 +332,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 +379,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(VPCI_C_OFFSET_Q_SIZE, c_cap.bar, &vq_size)) {
+            puts("Failed to read virt-queue configuration");
+            return -EIO;
+        }
+
+        info.num = vq_size;
+
+        if (vpci_read_bswap16(c_cap.off + VPCI_C_OFFSET_Q_NOFF, c_cap.bar, 
&vq_notify)) {
+            puts("Failed to read virt-queue configuration");
+            return -EIO;
+        }
For either of these error exits, do you need an identifier logged as to -which- 
virtqueue failed, as
you're in a loop?
Yes, that would certainly be useful information to have.  I'll add it.


+
+        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..993fc285ac 100644
--- a/pc-bios/s390-ccw/virtio-pci.h
+++ b/pc-bios/s390-ccw/virtio-pci.h
@@ -62,9 +62,10 @@ struct VirtioPciCap {
  };
  typedef struct VirtioPciCap  VirtioPciCap;
+int vpci_set_selected_vq(uint16_t queue_num);
  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 30e6b2bc16..00850acc2f 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;
      }
@@ -154,6 +155,7 @@ static void vr_bswap_descriptor(VRingDesc *desc)
  void vring_send_buf(VRing *vr, void *p, int len, int flags)
  {
      if (!be_ipl()) {
+        vpci_set_selected_vq(vr->id);
          vr->avail->idx = bswap16(vr->avail->idx);
      }
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;
Thank you for the review comments.

Regards,
Jared Rossi

Reply via email to