* [PATCH 1/4] virtio-mmio: wait for status readback after reset
2026-04-07 12:39 [PATCH 0/4] virtio: fix four bugs across mmio, pci, and vring Andrew Stellman
@ 2026-04-07 12:39 ` Andrew Stellman
2026-04-07 16:24 ` Michael S. Tsirkin
2026-04-07 12:39 ` [PATCH 2/4] virtio-pci: use avq->vq_index for admin VQ in INTx path Andrew Stellman
` (2 subsequent siblings)
3 siblings, 1 reply; 18+ messages in thread
From: Andrew Stellman @ 2026-04-07 12:39 UTC (permalink / raw)
To: Michael S . Tsirkin, Jason Wang
Cc: Xuan Zhuo, Eugenio Pérez, virtualization, Andrew Stellman
The virtio specification requires that after writing 0 to the status
register, the driver must wait until the device has actually completed
the reset (status reads back as 0) before proceeding. vm_reset() writes
0 but returns immediately without confirming the device has reset.
Add a poll loop matching the pattern already used in virtio-pci's
vp_reset(), which calls msleep(1) in a loop until the status register
reads 0.
Signed-off-by: Andrew Stellman <astellman@stellman-greene.com>
---
drivers/virtio/virtio_mmio.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 595c227..a477977 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -56,6 +56,7 @@
#include <linux/acpi.h>
#include <linux/dma-mapping.h>
+#include <linux/delay.h>
#include <linux/highmem.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -254,6 +255,8 @@ static void vm_reset(struct virtio_device *vdev)
/* 0 status means a reset. */
writel(0, vm_dev->base + VIRTIO_MMIO_STATUS);
+ while (readl(vm_dev->base + VIRTIO_MMIO_STATUS))
+ msleep(1);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH 1/4] virtio-mmio: wait for status readback after reset
2026-04-07 12:39 ` [PATCH 1/4] virtio-mmio: wait for status readback after reset Andrew Stellman
@ 2026-04-07 16:24 ` Michael S. Tsirkin
0 siblings, 0 replies; 18+ messages in thread
From: Michael S. Tsirkin @ 2026-04-07 16:24 UTC (permalink / raw)
To: Andrew Stellman; +Cc: Jason Wang, Xuan Zhuo, Eugenio Pérez, virtualization
On Tue, Apr 07, 2026 at 08:39:01AM -0400, Andrew Stellman wrote:
> The virtio specification requires that after writing 0 to the status
> register, the driver must wait until the device has actually completed
> the reset (status reads back as 0) before proceeding.
It does? But where?
I see:
Reading from this register returns the current device status
flags.
Writing non-zero values to this register sets the status flags,
indicating the OS/driver progress. Writing zero (0x0) to this
register triggers a device reset. The device
sets \field{QueuePFN} to zero (0x0) for all queues in the device.
> vm_reset() writes
> 0 but returns immediately without confirming the device has reset.
>
> Add a poll loop matching the pattern already used in virtio-pci's
> vp_reset(), which calls msleep(1) in a loop until the status register
> reads 0.
>
> Signed-off-by: Andrew Stellman <astellman@stellman-greene.com>
> ---
> drivers/virtio/virtio_mmio.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index 595c227..a477977 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -56,6 +56,7 @@
>
> #include <linux/acpi.h>
> #include <linux/dma-mapping.h>
> +#include <linux/delay.h>
> #include <linux/highmem.h>
> #include <linux/interrupt.h>
> #include <linux/io.h>
> @@ -254,6 +255,8 @@ static void vm_reset(struct virtio_device *vdev)
>
> /* 0 status means a reset. */
> writel(0, vm_dev->base + VIRTIO_MMIO_STATUS);
> + while (readl(vm_dev->base + VIRTIO_MMIO_STATUS))
> + msleep(1);
> }
>
>
> --
> 2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 2/4] virtio-pci: use avq->vq_index for admin VQ in INTx path
2026-04-07 12:39 [PATCH 0/4] virtio: fix four bugs across mmio, pci, and vring Andrew Stellman
2026-04-07 12:39 ` [PATCH 1/4] virtio-mmio: wait for status readback after reset Andrew Stellman
@ 2026-04-07 12:39 ` Andrew Stellman
2026-04-07 16:26 ` Michael S. Tsirkin
2026-04-07 12:39 ` [PATCH 3/4] virtio-pci: return IRQ_HANDLED for config-change interrupts Andrew Stellman
2026-04-07 12:39 ` [PATCH 4/4] virtio_ring: preserve VIRTIO_F_RING_RESET in transport features Andrew Stellman
3 siblings, 1 reply; 18+ messages in thread
From: Andrew Stellman @ 2026-04-07 12:39 UTC (permalink / raw)
To: Michael S . Tsirkin, Jason Wang
Cc: Xuan Zhuo, Eugenio Pérez, virtualization, Andrew Stellman
vp_find_vqs_intx() sets up the admin virtqueue using queue_idx++
(a sequential counter) instead of avq->vq_index (the actual transport
queue index). The MSI-X path in vp_find_vqs_msix() correctly uses
avq->vq_index. When the admin VQ index does not equal the next
sequential queue_idx value, the INTx path binds the admin VQ to the
wrong transport queue.
Use avq->vq_index to match the MSI-X path.
Signed-off-by: Andrew Stellman <astellman@stellman-greene.com>
---
drivers/virtio/virtio_pci_common.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index da97b6a..0b9d66b 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -497,7 +497,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned int nvqs,
if (!avq_num)
return 0;
sprintf(avq->name, "avq.%u", avq->vq_index);
- vq = vp_setup_vq(vdev, queue_idx++, vp_modern_avq_done, avq->name,
+ vq = vp_setup_vq(vdev, avq->vq_index, vp_modern_avq_done, avq->name,
false, VIRTIO_MSI_NO_VECTOR,
&vp_dev->admin_vq.info);
if (IS_ERR(vq)) {
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH 2/4] virtio-pci: use avq->vq_index for admin VQ in INTx path
2026-04-07 12:39 ` [PATCH 2/4] virtio-pci: use avq->vq_index for admin VQ in INTx path Andrew Stellman
@ 2026-04-07 16:26 ` Michael S. Tsirkin
[not found] ` <CAChPuV9OuQw_F5dsna4meVxV6Hicxe4+674xoSx+KEev6JEEQw@mail.gmail.com>
0 siblings, 1 reply; 18+ messages in thread
From: Michael S. Tsirkin @ 2026-04-07 16:26 UTC (permalink / raw)
To: Andrew Stellman
Cc: Jason Wang, Xuan Zhuo, Eugenio Pérez, virtualization,
Jiri Pirko
On Tue, Apr 07, 2026 at 08:39:02AM -0400, Andrew Stellman wrote:
> vp_find_vqs_intx() sets up the admin virtqueue using queue_idx++
> (a sequential counter) instead of avq->vq_index (the actual transport
> queue index). The MSI-X path in vp_find_vqs_msix() correctly uses
> avq->vq_index. When the admin VQ index does not equal the next
> sequential queue_idx value, the INTx path binds the admin VQ to the
> wrong transport queue.
>
> Use avq->vq_index to match the MSI-X path.
>
> Signed-off-by: Andrew Stellman <astellman@stellman-greene.com>
Cc Jiri. fixes tag?
> ---
> drivers/virtio/virtio_pci_common.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index da97b6a..0b9d66b 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -497,7 +497,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned int nvqs,
> if (!avq_num)
> return 0;
> sprintf(avq->name, "avq.%u", avq->vq_index);
> - vq = vp_setup_vq(vdev, queue_idx++, vp_modern_avq_done, avq->name,
> + vq = vp_setup_vq(vdev, avq->vq_index, vp_modern_avq_done, avq->name,
> false, VIRTIO_MSI_NO_VECTOR,
> &vp_dev->admin_vq.info);
> if (IS_ERR(vq)) {
> --
> 2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 3/4] virtio-pci: return IRQ_HANDLED for config-change interrupts
2026-04-07 12:39 [PATCH 0/4] virtio: fix four bugs across mmio, pci, and vring Andrew Stellman
2026-04-07 12:39 ` [PATCH 1/4] virtio-mmio: wait for status readback after reset Andrew Stellman
2026-04-07 12:39 ` [PATCH 2/4] virtio-pci: use avq->vq_index for admin VQ in INTx path Andrew Stellman
@ 2026-04-07 12:39 ` Andrew Stellman
2026-04-07 16:20 ` Michael S. Tsirkin
2026-09-03 15:14 ` Michael S. Tsirkin
2026-04-07 12:39 ` [PATCH 4/4] virtio_ring: preserve VIRTIO_F_RING_RESET in transport features Andrew Stellman
3 siblings, 2 replies; 18+ messages in thread
From: Andrew Stellman @ 2026-04-07 12:39 UTC (permalink / raw)
To: Michael S . Tsirkin, Jason Wang
Cc: Xuan Zhuo, Eugenio Pérez, virtualization, Andrew Stellman
vp_interrupt() unconditionally returns the result of
vp_vring_interrupt(). When a config-change interrupt fires but no vring
activity is pending, vp_vring_interrupt() returns IRQ_NONE — even
though the interrupt was legitimately handled by vp_config_changed().
Over time this causes the IRQ subsystem to flag the line as spurious.
Track the return value explicitly: set ret to IRQ_HANDLED when the
config-change bit is set, OR it with the vring result, and return the
combined value.
Signed-off-by: Andrew Stellman <astellman@stellman-greene.com>
---
drivers/virtio/virtio_pci_common.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 0b9d66b..1d1ab02 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -106,6 +106,7 @@ static irqreturn_t vp_vring_interrupt(int irq, void *opaque)
static irqreturn_t vp_interrupt(int irq, void *opaque)
{
struct virtio_pci_device *vp_dev = opaque;
+ irqreturn_t ret = IRQ_NONE;
u8 isr;
/* reading the ISR has the effect of also clearing it so it's very
@@ -117,10 +118,15 @@ static irqreturn_t vp_interrupt(int irq, void *opaque)
return IRQ_NONE;
/* Configuration change? Tell driver if it wants to know. */
- if (isr & VIRTIO_PCI_ISR_CONFIG)
+ if (isr & VIRTIO_PCI_ISR_CONFIG) {
vp_config_changed(irq, opaque);
+ ret = IRQ_HANDLED;
+ }
- return vp_vring_interrupt(irq, opaque);
+ if (vp_vring_interrupt(irq, opaque) == IRQ_HANDLED)
+ ret = IRQ_HANDLED;
+
+ return ret;
}
static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH 3/4] virtio-pci: return IRQ_HANDLED for config-change interrupts
2026-04-07 12:39 ` [PATCH 3/4] virtio-pci: return IRQ_HANDLED for config-change interrupts Andrew Stellman
@ 2026-04-07 16:20 ` Michael S. Tsirkin
[not found] ` <CAChPuV9iGu6o5yJz87DEo6=gfr2P7m_jM=-auFuZevrr-HoYNw@mail.gmail.com>
2026-09-03 15:14 ` Michael S. Tsirkin
1 sibling, 1 reply; 18+ messages in thread
From: Michael S. Tsirkin @ 2026-04-07 16:20 UTC (permalink / raw)
To: Andrew Stellman; +Cc: Jason Wang, Xuan Zhuo, Eugenio Pérez, virtualization
On Tue, Apr 07, 2026 at 08:39:03AM -0400, Andrew Stellman wrote:
> vp_interrupt() unconditionally returns the result of
> vp_vring_interrupt(). When a config-change interrupt fires but no vring
> activity is pending, vp_vring_interrupt() returns IRQ_NONE — even
> though the interrupt was legitimately handled by vp_config_changed().
> Over time this causes the IRQ subsystem to flag the line as spurious.
>
> Track the return value explicitly: set ret to IRQ_HANDLED when the
> config-change bit is set, OR it with the vring result, and return the
> combined value.
>
> Signed-off-by: Andrew Stellman <astellman@stellman-greene.com>
Fixes tag?
> ---
> drivers/virtio/virtio_pci_common.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index 0b9d66b..1d1ab02 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -106,6 +106,7 @@ static irqreturn_t vp_vring_interrupt(int irq, void *opaque)
> static irqreturn_t vp_interrupt(int irq, void *opaque)
> {
> struct virtio_pci_device *vp_dev = opaque;
> + irqreturn_t ret = IRQ_NONE;
> u8 isr;
>
> /* reading the ISR has the effect of also clearing it so it's very
> @@ -117,10 +118,15 @@ static irqreturn_t vp_interrupt(int irq, void *opaque)
> return IRQ_NONE;
>
> /* Configuration change? Tell driver if it wants to know. */
> - if (isr & VIRTIO_PCI_ISR_CONFIG)
> + if (isr & VIRTIO_PCI_ISR_CONFIG) {
> vp_config_changed(irq, opaque);
> + ret = IRQ_HANDLED;
> + }
>
> - return vp_vring_interrupt(irq, opaque);
> + if (vp_vring_interrupt(irq, opaque) == IRQ_HANDLED)
> + ret = IRQ_HANDLED;
> +
> + return ret;
> }
>
> static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
> --
> 2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH 3/4] virtio-pci: return IRQ_HANDLED for config-change interrupts
2026-04-07 12:39 ` [PATCH 3/4] virtio-pci: return IRQ_HANDLED for config-change interrupts Andrew Stellman
2026-04-07 16:20 ` Michael S. Tsirkin
@ 2026-09-03 15:14 ` Michael S. Tsirkin
2026-09-03 19:07 ` [PATCH v2 3/4] virtio-pci: return IRQ_HANDLED after non-zero ISR Andrew Stellman
1 sibling, 1 reply; 18+ messages in thread
From: Michael S. Tsirkin @ 2026-09-03 15:14 UTC (permalink / raw)
To: Andrew Stellman; +Cc: Jason Wang, Xuan Zhuo, Eugenio Pérez, virtualization
On Tue, Apr 07, 2026 at 08:39:03AM -0400, Andrew Stellman wrote:
> vp_interrupt() unconditionally returns the result of
> vp_vring_interrupt(). When a config-change interrupt fires but no vring
> activity is pending, vp_vring_interrupt() returns IRQ_NONE — even
> though the interrupt was legitimately handled by vp_config_changed().
> Over time this causes the IRQ subsystem to flag the line as spurious.
>
> Track the return value explicitly: set ret to IRQ_HANDLED when the
> config-change bit is set, OR it with the vring result, and return the
> combined value.
>
> Signed-off-by: Andrew Stellman <astellman@stellman-greene.com>
> ---
> drivers/virtio/virtio_pci_common.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index 0b9d66b..1d1ab02 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -106,6 +106,7 @@ static irqreturn_t vp_vring_interrupt(int irq, void *opaque)
> static irqreturn_t vp_interrupt(int irq, void *opaque)
> {
> struct virtio_pci_device *vp_dev = opaque;
> + irqreturn_t ret = IRQ_NONE;
> u8 isr;
>
> /* reading the ISR has the effect of also clearing it so it's very
> @@ -117,10 +118,15 @@ static irqreturn_t vp_interrupt(int irq, void *opaque)
> return IRQ_NONE;
>
> /* Configuration change? Tell driver if it wants to know. */
> - if (isr & VIRTIO_PCI_ISR_CONFIG)
> + if (isr & VIRTIO_PCI_ISR_CONFIG) {
> vp_config_changed(irq, opaque);
> + ret = IRQ_HANDLED;
> + }
>
> - return vp_vring_interrupt(irq, opaque);
> + if (vp_vring_interrupt(irq, opaque) == IRQ_HANDLED)
> + ret = IRQ_HANDLED;
> +
> + return ret;
> }
So I think as long as we are looking at isr, let's look
at isr exclusively?
we cleared it so ... all well?
return IRQ_HANDLED and be done with it?
> static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
> --
> 2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread* [PATCH v2 3/4] virtio-pci: return IRQ_HANDLED after non-zero ISR
2026-09-03 15:14 ` Michael S. Tsirkin
@ 2026-09-03 19:07 ` Andrew Stellman
2026-09-04 7:27 ` Michael S. Tsirkin
2026-09-04 7:30 ` Michael S. Tsirkin
0 siblings, 2 replies; 18+ messages in thread
From: Andrew Stellman @ 2026-09-03 19:07 UTC (permalink / raw)
To: mst; +Cc: jasowang, xuanzhuo, eperezma, virtualization
vp_interrupt() reads the ISR before dispatching config-change and
vring handling. Reading the ISR also clears it, so once the read
returns non-zero the interrupt was from this device and has already
been consumed.
Currently vp_interrupt() returns the result of vp_vring_interrupt().
For a config-change interrupt with no vring work, that can return
IRQ_NONE even though the ISR was non-zero and the interrupt was
handled.
Call vp_vring_interrupt() for any queue work, but once the ISR is
non-zero return IRQ_HANDLED.
Tested with QEMU virtio-blk-pci forced to INTx using vectors=0 and
pci=nomsi. On an idle device, 200 config-change interrupts were
generated using QMP block_resize.
Before this change, irq_handler_exit reported ret=unhandled and
/proc/irq/11/spurious increased from 0 to 200 unhandled interrupts.
After this change, irq_handler_exit reported ret=handled and the
unhandled count remained at 0.
Fixes: 77cf524654a8 ("virtio_pci: split up vp_interrupt")
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Andrew Stellman <astellman@stellman-greene.com>
---
Changes from v1:
- Return IRQ_HANDLED for any non-zero ISR, as suggested by Michael.
- Add Fixes and Suggested-by tags.
- Test the change with virtio-blk forced to legacy INTx under QEMU.
Full red/green test logs and the exact tested patch:
https://github.com/andrewstellman/quality-playbook/tree/11ba61d/evidence/virtio-pci-intx
drivers/virtio/virtio_pci_common.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 10371ecbc054..b90c174450b2 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -120,7 +120,9 @@ static irqreturn_t vp_interrupt(int irq, void *opaque)
if (isr & VIRTIO_PCI_ISR_CONFIG)
vp_config_changed(irq, opaque);
- return vp_vring_interrupt(irq, opaque);
+ vp_vring_interrupt(irq, opaque);
+
+ return IRQ_HANDLED;
}
static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v2 3/4] virtio-pci: return IRQ_HANDLED after non-zero ISR
2026-09-03 19:07 ` [PATCH v2 3/4] virtio-pci: return IRQ_HANDLED after non-zero ISR Andrew Stellman
@ 2026-09-04 7:27 ` Michael S. Tsirkin
2026-09-04 7:30 ` Michael S. Tsirkin
1 sibling, 0 replies; 18+ messages in thread
From: Michael S. Tsirkin @ 2026-09-04 7:27 UTC (permalink / raw)
To: Andrew Stellman; +Cc: jasowang, xuanzhuo, eperezma, virtualization
On Thu, Sep 03, 2026 at 03:07:31PM -0400, Andrew Stellman wrote:
> vp_interrupt() reads the ISR before dispatching config-change and
> vring handling. Reading the ISR also clears it, so once the read
> returns non-zero the interrupt was from this device and has already
> been consumed.
>
> Currently vp_interrupt() returns the result of vp_vring_interrupt().
> For a config-change interrupt with no vring work, that can return
> IRQ_NONE even though the ISR was non-zero and the interrupt was
> handled.
>
> Call vp_vring_interrupt() for any queue work, but once the ISR is
> non-zero return IRQ_HANDLED.
>
> Tested with QEMU virtio-blk-pci forced to INTx using vectors=0 and
> pci=nomsi. On an idle device, 200 config-change interrupts were
> generated using QMP block_resize.
>
> Before this change, irq_handler_exit reported ret=unhandled and
> /proc/irq/11/spurious increased from 0 to 200 unhandled interrupts.
> After this change, irq_handler_exit reported ret=handled and the
> unhandled count remained at 0.
>
> Fixes: 77cf524654a8 ("virtio_pci: split up vp_interrupt")
Where did you get this fixes tag?
It's been like this from the beginning:
+static irqreturn_t vp_interrupt(int irq, void *opaque)
+{
+ struct virtio_pci_device *vp_dev = opaque;
+ struct virtio_pci_vq_info *info;
+ irqreturn_t ret = IRQ_NONE;
+ u8 isr;
+
+ /* reading the ISR has the effect of also clearing it so it's very
+ * important to save off the value. */
+ isr = ioread8(vp_dev->ioaddr + VIRTIO_PCI_ISR);
+
+ /* It's definitely not us if the ISR was not high */
+ if (!isr)
+ return IRQ_NONE;
+
+ /* Configuration change? Tell driver if it wants to know. */
+ if (isr & VIRTIO_PCI_ISR_CONFIG) {
+ struct virtio_driver *drv;
+ drv = container_of(vp_dev->vdev.dev.driver,
+ struct virtio_driver, driver);
+
+ if (drv->config_changed)
+ drv->config_changed(&vp_dev->vdev);
+ }
+
+ spin_lock(&vp_dev->lock);
+ list_for_each_entry(info, &vp_dev->virtqueues, node) {
+ if (vring_interrupt(irq, info->vq) == IRQ_HANDLED)
+ ret = IRQ_HANDLED;
+ }
+ spin_unlock(&vp_dev->lock);
+
+ return ret;
+}
So really:
Fixes: 3343660d8c62 ("virtio: PCI device")
> Suggested-by: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Andrew Stellman <astellman@stellman-greene.com>
> ---
> Changes from v1:
> - Return IRQ_HANDLED for any non-zero ISR, as suggested by Michael.
> - Add Fixes and Suggested-by tags.
> - Test the change with virtio-blk forced to legacy INTx under QEMU.
>
> Full red/green test logs and the exact tested patch:
> https://github.com/andrewstellman/quality-playbook/tree/11ba61d/evidence/virtio-pci-intx
>
> drivers/virtio/virtio_pci_common.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index 10371ecbc054..b90c174450b2 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -120,7 +120,9 @@ static irqreturn_t vp_interrupt(int irq, void *opaque)
> if (isr & VIRTIO_PCI_ISR_CONFIG)
> vp_config_changed(irq, opaque);
>
> - return vp_vring_interrupt(irq, opaque);
> + vp_vring_interrupt(irq, opaque);
> +
> + return IRQ_HANDLED;
> }
>
> static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
> --
> 2.43.0
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH v2 3/4] virtio-pci: return IRQ_HANDLED after non-zero ISR
2026-09-03 19:07 ` [PATCH v2 3/4] virtio-pci: return IRQ_HANDLED after non-zero ISR Andrew Stellman
2026-09-04 7:27 ` Michael S. Tsirkin
@ 2026-09-04 7:30 ` Michael S. Tsirkin
1 sibling, 0 replies; 18+ messages in thread
From: Michael S. Tsirkin @ 2026-09-04 7:30 UTC (permalink / raw)
To: Andrew Stellman; +Cc: jasowang, xuanzhuo, eperezma, virtualization
On Thu, Sep 03, 2026 at 03:07:31PM -0400, Andrew Stellman wrote:
> vp_interrupt() reads the ISR before dispatching config-change and
> vring handling. Reading the ISR also clears it, so once the read
> returns non-zero the interrupt was from this device and has already
> been consumed.
>
> Currently vp_interrupt() returns the result of vp_vring_interrupt().
> For a config-change interrupt with no vring work, that can return
> IRQ_NONE even though the ISR was non-zero and the interrupt was
> handled.
>
> Call vp_vring_interrupt() for any queue work, but once the ISR is
> non-zero return IRQ_HANDLED.
>
> Tested with QEMU virtio-blk-pci forced to INTx using vectors=0 and
> pci=nomsi. On an idle device, 200 config-change interrupts were
> generated using QMP block_resize.
>
> Before this change, irq_handler_exit reported ret=unhandled and
> /proc/irq/11/spurious increased from 0 to 200 unhandled interrupts.
> After this change, irq_handler_exit reported ret=handled and the
> unhandled count remained at 0.
>
> Fixes: 77cf524654a8 ("virtio_pci: split up vp_interrupt")
> Suggested-by: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Andrew Stellman <astellman@stellman-greene.com>
besides pls do not post new versions as
replies to old one.
and I think this patch is unrelated to
others in this thread, right?
so just post it separately.
thanks!
> ---
> Changes from v1:
> - Return IRQ_HANDLED for any non-zero ISR, as suggested by Michael.
> - Add Fixes and Suggested-by tags.
> - Test the change with virtio-blk forced to legacy INTx under QEMU.
>
> Full red/green test logs and the exact tested patch:
> https://github.com/andrewstellman/quality-playbook/tree/11ba61d/evidence/virtio-pci-intx
>
> drivers/virtio/virtio_pci_common.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index 10371ecbc054..b90c174450b2 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -120,7 +120,9 @@ static irqreturn_t vp_interrupt(int irq, void *opaque)
> if (isr & VIRTIO_PCI_ISR_CONFIG)
> vp_config_changed(irq, opaque);
>
> - return vp_vring_interrupt(irq, opaque);
> + vp_vring_interrupt(irq, opaque);
> +
> + return IRQ_HANDLED;
> }
>
> static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
> --
> 2.43.0
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 4/4] virtio_ring: preserve VIRTIO_F_RING_RESET in transport features
2026-04-07 12:39 [PATCH 0/4] virtio: fix four bugs across mmio, pci, and vring Andrew Stellman
` (2 preceding siblings ...)
2026-04-07 12:39 ` [PATCH 3/4] virtio-pci: return IRQ_HANDLED for config-change interrupts Andrew Stellman
@ 2026-04-07 12:39 ` Andrew Stellman
2026-04-07 16:21 ` Michael S. Tsirkin
3 siblings, 1 reply; 18+ messages in thread
From: Andrew Stellman @ 2026-04-07 12:39 UTC (permalink / raw)
To: Michael S . Tsirkin, Jason Wang
Cc: Xuan Zhuo, Eugenio Pérez, virtualization, Andrew Stellman
vring_transport_features() whitelists known transport feature bits and
clears the rest via __virtio_clear_bit(). VIRTIO_F_RING_RESET is
missing from the whitelist, so it is unconditionally cleared during
feature negotiation. Drivers that depend on ring reset capability
silently lose the feature.
Add VIRTIO_F_RING_RESET to the switch statement, matching the other
transport-level features.
Signed-off-by: Andrew Stellman <astellman@stellman-greene.com>
---
drivers/virtio/virtio_ring.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index fbca7ce..2cb643f 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -3524,6 +3524,8 @@ void vring_transport_features(struct virtio_device *vdev)
break;
case VIRTIO_F_IN_ORDER:
break;
+ case VIRTIO_F_RING_RESET:
+ break;
default:
/* We don't understand this bit. */
__virtio_clear_bit(vdev, i);
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH 4/4] virtio_ring: preserve VIRTIO_F_RING_RESET in transport features
2026-04-07 12:39 ` [PATCH 4/4] virtio_ring: preserve VIRTIO_F_RING_RESET in transport features Andrew Stellman
@ 2026-04-07 16:21 ` Michael S. Tsirkin
[not found] ` <CAChPuV92aD4BibJiGfMASQVQBHAoz+3OgzQS6Hb2Dw7JDcRJTQ@mail.gmail.com>
0 siblings, 1 reply; 18+ messages in thread
From: Michael S. Tsirkin @ 2026-04-07 16:21 UTC (permalink / raw)
To: Andrew Stellman; +Cc: Jason Wang, Xuan Zhuo, Eugenio Pérez, virtualization
On Tue, Apr 07, 2026 at 08:39:04AM -0400, Andrew Stellman wrote:
> vring_transport_features() whitelists known transport feature bits and
> clears the rest via __virtio_clear_bit(). VIRTIO_F_RING_RESET is
> missing from the whitelist, so it is unconditionally cleared during
> feature negotiation. Drivers that depend on ring reset capability
> silently lose the feature.
Hmm was this observed in practice or just from code analysis?
And on which transport?
Because
static void vp_transport_features(struct virtio_device *vdev, u64 features)
{
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
struct pci_dev *pci_dev = vp_dev->pci_dev;
if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
if (features & BIT_ULL(VIRTIO_F_RING_RESET))
__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
...
}
> Add VIRTIO_F_RING_RESET to the switch statement, matching the other
> transport-level features.
>
> Signed-off-by: Andrew Stellman <astellman@stellman-greene.com>
> ---
> drivers/virtio/virtio_ring.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index fbca7ce..2cb643f 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -3524,6 +3524,8 @@ void vring_transport_features(struct virtio_device *vdev)
> break;
> case VIRTIO_F_IN_ORDER:
> break;
> + case VIRTIO_F_RING_RESET:
> + break;
> default:
> /* We don't understand this bit. */
> __virtio_clear_bit(vdev, i);
> --
> 2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread