]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
hisi_acc_vfio_pci: fix VF reset timeout issue
authorWeili Qian <qianweili@huawei.com>
Thu, 22 Jan 2026 02:02:02 +0000 (10:02 +0800)
committerAlex Williamson <alex@shazbot.org>
Thu, 29 Jan 2026 21:11:00 +0000 (14:11 -0700)
If device error occurs during live migration, qemu will
reset the VF. At this time, VF reset and device reset are performed
simultaneously. The VF reset will timeout. Therefore, the QM_RESETTING
flag is used to ensure that VF reset and device reset are performed
serially.

Fixes: b0eed085903e ("hisi_acc_vfio_pci: Add support for VFIO live migration")
Signed-off-by: Weili Qian <qianweili@huawei.com>
Link: https://lore.kernel.org/r/20260122020205.2884497-2-liulongfang@huawei.com
Signed-off-by: Alex Williamson <alex@shazbot.org>
drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h

index cf45f6370c36985f07fe77b31c816c4d92011c16..d1e8053640a98cec785dba6e260afda497012f67 100644 (file)
@@ -1188,9 +1188,32 @@ hisi_acc_vfio_pci_get_device_state(struct vfio_device *vdev,
        return 0;
 }
 
+static void hisi_acc_vf_pci_reset_prepare(struct pci_dev *pdev)
+{
+       struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_drvdata(pdev);
+       struct hisi_qm *qm = hisi_acc_vdev->pf_qm;
+       struct device *dev = &qm->pdev->dev;
+       u32 delay = 0;
+
+       /* All reset requests need to be queued for processing */
+       while (test_and_set_bit(QM_RESETTING, &qm->misc_ctl)) {
+               msleep(1);
+               if (++delay > QM_RESET_WAIT_TIMEOUT) {
+                       dev_err(dev, "reset prepare failed\n");
+                       return;
+               }
+       }
+
+       hisi_acc_vdev->set_reset_flag = true;
+}
+
 static void hisi_acc_vf_pci_aer_reset_done(struct pci_dev *pdev)
 {
        struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_drvdata(pdev);
+       struct hisi_qm *qm = hisi_acc_vdev->pf_qm;
+
+       if (hisi_acc_vdev->set_reset_flag)
+               clear_bit(QM_RESETTING, &qm->misc_ctl);
 
        if (hisi_acc_vdev->core_device.vdev.migration_flags !=
                                VFIO_MIGRATION_STOP_COPY)
@@ -1734,6 +1757,7 @@ static const struct pci_device_id hisi_acc_vfio_pci_table[] = {
 MODULE_DEVICE_TABLE(pci, hisi_acc_vfio_pci_table);
 
 static const struct pci_error_handlers hisi_acc_vf_err_handlers = {
+       .reset_prepare = hisi_acc_vf_pci_reset_prepare,
        .reset_done = hisi_acc_vf_pci_aer_reset_done,
        .error_detected = vfio_pci_core_aer_err_detected,
 };
index cd55eba64dfb238f209e5e58ae0990bcb7d6444f..a3d91a31e3d8866f0c70238799453d06f9a6d580 100644 (file)
@@ -27,6 +27,7 @@
 
 #define ERROR_CHECK_TIMEOUT            100
 #define CHECK_DELAY_TIME               100
+#define QM_RESET_WAIT_TIMEOUT  60000
 
 #define QM_SQC_VFT_BASE_SHIFT_V2       28
 #define QM_SQC_VFT_BASE_MASK_V2                GENMASK(15, 0)
@@ -128,6 +129,7 @@ struct hisi_acc_vf_migration_file {
 struct hisi_acc_vf_core_device {
        struct vfio_pci_core_device core_device;
        u8 match_done;
+       bool set_reset_flag;
        /*
         * io_base is only valid when dev_opened is true,
         * which is protected by open_mutex.