[PATCH v2 1/2] virtio-pci: add error_detected for PCI AER recovery

From: Xixin Liu

Date: Fri Jul 31 2026 - 04:30:18 EST


virtio-pci only registered reset_prepare/reset_done. The PCI error
recovery core treats devices without error_detected as NO_AER_DRIVER and
does not deliver pci_channel_io_perm_failure to the driver after a failed
recovery. Virtio devices therefore miss the normal ERS quiesce/teardown
sequence.

Register error_detected: quiesce on frozen (reset_prepare) before bus
reset; on perm_failure break virtqueues and return DISCONNECT. Block-layer
cleanup for virtio-blk is handled in the follow-up patch.

Assisted-by: DeepSeek:deepseek-v3
Signed-off-by: Xixin Liu <liuxixin@xxxxxxxxxx>
---
drivers/virtio/virtio_pci_common.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)

diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 164f480b18a6..fff6b6e2d0c5 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -828,7 +828,37 @@ static void virtio_pci_reset_done(struct pci_dev *pci_dev)
dev_warn(&pci_dev->dev, "Reset done failure: %d", ret);
}

+static pci_ers_result_t virtio_pci_error_detected(struct pci_dev *pci_dev,
+ pci_channel_state_t state)
+{
+ struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
+
+ /*
+ * PCI ERS error_detected: quiesce on frozen before bus reset; on
+ * permanent failure break virtqueues (follow-up may call driver
+ * .shutdown for block teardown).
+ */
+ switch (state) {
+ case pci_channel_io_normal:
+ return PCI_ERS_RESULT_CAN_RECOVER;
+ case pci_channel_io_frozen:
+ pci_info(pci_dev, "frozen error detected, quiesce device\n");
+ if (virtio_device_reset_prepare(&vp_dev->vdev))
+ dev_warn(&pci_dev->dev, "frozen: reset prepare failed\n");
+ return PCI_ERS_RESULT_NEED_RESET;
+ case pci_channel_io_perm_failure:
+ dev_warn(&pci_dev->dev,
+ "permanent failure, disconnecting device\n");
+ virtio_break_device(&vp_dev->vdev);
+ return PCI_ERS_RESULT_DISCONNECT;
+ default:
+ break;
+ }
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
static const struct pci_error_handlers virtio_pci_err_handler = {
+ .error_detected = virtio_pci_error_detected,
.reset_prepare = virtio_pci_reset_prepare,
.reset_done = virtio_pci_reset_done,
};
--
2.43.0