lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <22e7b32bfe524219eb7ff1e5c6b4d91763b79eef.1755327132.git.lukas@wunner.de>
Date: Sat, 16 Aug 2025 09:10:03 +0200
From: Lukas Wunner <lukas@...ner.de>
To: Tony Nguyen <anthony.l.nguyen@...el.com>, Przemek Kitszel <przemyslaw.kitszel@...el.com>
Cc: intel-wired-lan@...ts.osuosl.org, netdev@...r.kernel.org
Subject: [PATCH 3/3] i40e: Fix enable_cnt imbalance on PCIe error recovery

After a PCIe Uncorrectable Error has been reported by an i40e adapter
and has been recovered through a Secondary Bus Reset, its driver calls
pci_enable_device() 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() has almost no effect because the
enable_cnt was already incremented in i40e_probe() through the call to
pci_enable_device_mem().  The subsequent pci_enable_device() thus bails
out after invoking pci_update_current_state().

Remove pci_enable_device().  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() 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: 41c445ff0f48 ("i40e: main driver core")
Signed-off-by: Lukas Wunner <lukas@...ner.de>
Cc: stable@...r.kernel.org  # v3.12+
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 29 +++++++--------------
 1 file changed, 10 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 9d6d892602fa..7e87234fde67 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -16439,29 +16439,20 @@ static pci_ers_result_t i40e_pci_error_detected(struct pci_dev *pdev,
 static pci_ers_result_t i40e_pci_error_slot_reset(struct pci_dev *pdev)
 {
 	struct i40e_pf *pf = pci_get_drvdata(pdev);
-	pci_ers_result_t result;
 	u32 reg;
 
 	dev_dbg(&pdev->dev, "%s\n", __func__);
-	/* enable I/O and memory of the device  */
-	if (pci_enable_device(pdev)) {
-		dev_info(&pdev->dev,
-			 "Cannot re-enable PCI device after reset.\n");
-		result = PCI_ERS_RESULT_DISCONNECT;
-	} else {
-		pci_set_master(pdev);
-		pci_restore_state(pdev);
-		pci_save_state(pdev);
-		pci_wake_from_d3(pdev, false);
-
-		reg = rd32(&pf->hw, I40E_GLGEN_RTRIG);
-		if (reg == 0)
-			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;
+	reg = rd32(&pf->hw, I40E_GLGEN_RTRIG);
+	if (reg == 0)
+		return PCI_ERS_RESULT_RECOVERED;
+	else
+		return PCI_ERS_RESULT_DISCONNECT;
 }
 
 /**
-- 
2.47.2


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ