]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
crypto: qat - improve aer error reset handling
authorMun Chun Yep <mun.chun.yep@intel.com>
Fri, 2 Feb 2024 10:53:24 +0000 (18:53 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 9 Feb 2024 04:57:18 +0000 (12:57 +0800)
Rework the AER reset and recovery flow to take into account root port
integrated devices that gets reset between the error detected and the
slot reset callbacks.

In adf_error_detected() the devices is gracefully shut down. The worker
threads are disabled, the error conditions are notified to listeners and
through PFVF comms and finally the device is reset as part of
adf_dev_down().

In adf_slot_reset(), the device is brought up again. If SRIOV VFs were
enabled before reset, these are re-enabled and VFs are notified of
restarting through PFVF comms.

Signed-off-by: Mun Chun Yep <mun.chun.yep@intel.com>
Reviewed-by: Ahsan Atta <ahsan.atta@intel.com>
Reviewed-by: Markas Rapoportas <markas.rapoportas@intel.com>
Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/intel/qat/qat_common/adf_aer.c

index b3d4b6b99c65a144df431f4e4ed6b5686ec74007..3597e7605a143c2f5a560d4285225450d0e08a0d 100644 (file)
@@ -33,6 +33,19 @@ static pci_ers_result_t adf_error_detected(struct pci_dev *pdev,
                return PCI_ERS_RESULT_DISCONNECT;
        }
 
+       set_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
+       if (accel_dev->hw_device->exit_arb) {
+               dev_dbg(&pdev->dev, "Disabling arbitration\n");
+               accel_dev->hw_device->exit_arb(accel_dev);
+       }
+       adf_error_notifier(accel_dev);
+       adf_pf2vf_notify_fatal_error(accel_dev);
+       adf_dev_restarting_notify(accel_dev);
+       adf_pf2vf_notify_restarting(accel_dev);
+       adf_pf2vf_wait_for_restarting_complete(accel_dev);
+       pci_clear_master(pdev);
+       adf_dev_down(accel_dev, false);
+
        return PCI_ERS_RESULT_NEED_RESET;
 }
 
@@ -180,14 +193,25 @@ static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev,
 static pci_ers_result_t adf_slot_reset(struct pci_dev *pdev)
 {
        struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
+       int res = 0;
 
        if (!accel_dev) {
                pr_err("QAT: Can't find acceleration device\n");
                return PCI_ERS_RESULT_DISCONNECT;
        }
-       if (adf_dev_aer_schedule_reset(accel_dev, ADF_DEV_RESET_SYNC))
+
+       if (!pdev->is_busmaster)
+               pci_set_master(pdev);
+       pci_restore_state(pdev);
+       pci_save_state(pdev);
+       res = adf_dev_up(accel_dev, false);
+       if (res && res != -EALREADY)
                return PCI_ERS_RESULT_DISCONNECT;
 
+       adf_reenable_sriov(accel_dev);
+       adf_pf2vf_notify_restarted(accel_dev);
+       adf_dev_restarted_notify(accel_dev);
+       clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
        return PCI_ERS_RESULT_RECOVERED;
 }