diff mbox series

[2/3] ice: Fix enable_cnt imbalance on PCIe error recovery

Message ID 525e494c981747ef2cdd666c50870b69aabf94af.1755327132.git.lukas@wunner.de
State Needs Review / ACK
Delegated to: Anthony Nguyen
Headers show
Series ice/i40e: pci_enable_device() fixes | expand

Commit Message

Lukas Wunner Aug. 16, 2025, 7:10 a.m. UTC
After a PCIe Uncorrectable Error has been reported by an ice adapter
and has been recovered through a Secondary Bus Reset, its driver calls
pci_enable_device_mem() without having called pci_disable_device().

This leads to an imbalance of the enable_cnt tracked by the PCI core:
Every time error recovery occurs, the enable_cnt keeps growing.  If it
occurs at least once and the driver is then unbound, the device isn't
disabled since the enable_cnt hasn't reached zero (and never again will).

The call to pci_enable_device_mem() has almost no effect because the
enable_cnt was already incremented in ice_probe() through the call to
pcim_enable_device().  The subsequent pci_enable_device_mem() thus bails
out after invoking pci_update_current_state().

Remove pci_enable_device_mem().  In lieu of pci_update_current_state(),
set the power state to D0 because that's the power state after a
Secondary Bus Reset (PCIe r7.0 sec 5.3.1.1).

The intended purpose of pci_enable_device_mem() may have been to set
the Memory Space Enable bit in the Command register again after reset,
but that is already achieved by the subsequent call to
pci_restore_state().

Fixes: 5995b6d0c6fc ("ice: Implement pci_error_handler ops")
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: stable@vger.kernel.org  # v5.2+
---
 drivers/net/ethernet/intel/ice/ice_main.c | 32 ++++++++---------------
 1 file changed, 11 insertions(+), 21 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 3be4347223ef..848d5b512319 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5720,30 +5720,20 @@  ice_pci_err_detected(struct pci_dev *pdev, pci_channel_state_t err)
 static pci_ers_result_t ice_pci_err_slot_reset(struct pci_dev *pdev)
 {
 	struct ice_pf *pf = pci_get_drvdata(pdev);
-	pci_ers_result_t result;
-	int err;
 	u32 reg;
 
-	err = pci_enable_device_mem(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "Cannot re-enable PCI device after reset, error %d\n",
-			err);
-		result = PCI_ERS_RESULT_DISCONNECT;
-	} else {
-		pci_set_master(pdev);
-		pci_restore_state(pdev);
-		pci_save_state(pdev);
-		pci_wake_from_d3(pdev, false);
-
-		/* Check for life */
-		reg = rd32(&pf->hw, GLGEN_RTRIG);
-		if (!reg)
-			result = PCI_ERS_RESULT_RECOVERED;
-		else
-			result = PCI_ERS_RESULT_DISCONNECT;
-	}
+	pdev->current_state = PCI_D0;
+	pci_set_master(pdev);
+	pci_restore_state(pdev);
+	pci_save_state(pdev);
+	pci_wake_from_d3(pdev, false);
 
-	return result;
+	/* Check for life */
+	reg = rd32(&pf->hw, GLGEN_RTRIG);
+	if (!reg)
+		return PCI_ERS_RESULT_RECOVERED;
+	else
+		return PCI_ERS_RESULT_DISCONNECT;
 }
 
 /**