mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH wireless v3 0/4] wifi: iwlwifi: recover the BE200 after D3cold removes its power
@ 2026-09-13 21:14 Navon John Lukose
  2026-09-13 21:14 ` [PATCH wireless v3 1/4] wifi: iwlwifi: pcie: cancel the ME recheck work on probe failure Navon John Lukose
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Navon John Lukose @ 2026-09-13 21:14 UTC (permalink / raw)
  To: miriam.rachel.korenblit, linux-wireless
  Cc: johannes, helgaas, ilpo.jarvinen, emmanuel.grumbach, nika,
	mpearson-lenovo, linux-pci, linux-kernel, Navon John Lukose

On a Lenovo Yoga Pro 7 14IAH10 the Intel Wi-Fi 7 BE200 (8086:272b) does not
survive D3cold. _PR3 removes the M.2 module's rail, and when the rail and
PERST# come back the card never restarts. The link does not train and
config space reads 0xffffffff until reboot.

Nothing here is BE200-specific. Patch 4's arming is gated on !integrated,
and the AML gate on this board also accepts 0x2526/0x271b (9000 series),
0x2723 (AX200) and 0x2725 (AX210). BE200 is the only one I have and the
only one I tested.

  Patch 1  cancel the ME recheck work on the probe error path.
  Patch 2  stop inferring CSME presence from a read that never landed.
  Patch 3  deselect the product reset mode at probe.
  Patch 4  arm the mode in .suspend, disarm in .resume, and reset when the
           disarm fails and the device reads all ones.

+60/-10. Patches 1 to 3 carry Fixes: and Cc: stable. Patch 4 has no Fixes:
and is Cc: stable+noautosel, because the device dying in D3cold is not a
regression from any commit. The driver simply never handled it.

The DMI quirk patch 4 Links to disables D3cold on the affected machines,
which keeps the module's rail up for every runtime idle from then on. This
keeps D3cold and pays ~7 s on the resumes that fail. Patches 1 to 3 stand
alone if you would rather take the quirk.

Tested on one machine, one BIOS, discrete only, with s2idle and hibernate.
s2idle was broken before this and is fixed now. Hibernate was never broken
and still works with the arming in .freeze. Methodology and the untested
surface are under the --- of patch 4.

Since v2:
https://lore.kernel.org/all/20260831130332.323549-1-navonjohnlukose@gmail.com/

- The ME recheck cancel, sent on its own before, is folded in as patch 1 so
  patch 2 does not widen the use-after-free it closes.
- Bjorn: the new tests use PCI_POSSIBLE_ERROR().
- Ilpo: str_enable_disable(). The same line now prints the error with %pe.

v1: https://lore.kernel.org/all/20260829095437.44716-1-navonjohnlukose@gmail.com/

Signed-off-by: Navon John Lukose <navonjohnlukose@gmail.com>

Navon John Lukose (4):
  wifi: iwlwifi: pcie: cancel the ME recheck work on probe failure
  wifi: iwlwifi: pcie: don't infer CSME presence from a failed read
  wifi: iwlwifi: pcie: deselect the product reset mode at probe
  wifi: iwlwifi: pcie: recover a device that lost power in D3cold

 drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 24 +++++++++++
 .../intel/iwlwifi/pcie/gen1_2/internal.h      |  4 ++
 .../intel/iwlwifi/pcie/gen1_2/trans.c         | 42 ++++++++++++++-----
 3 files changed, 60 insertions(+), 10 deletions(-)

Interdiff against v2:

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 5d01a4d..80d6c25 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -1245,7 +1245,7 @@ static int _iwl_pci_resume(struct device *device, bool restore)
 	if (trans_pcie->prod_reset_set) {
 		iwl_trans_pcie_arm_product_reset(trans, false);
 		if (trans_pcie->prod_reset_set &&
-		    iwl_read32(trans, CSR_HW_REV) == ~0U) {
+		    PCI_POSSIBLE_ERROR(iwl_read32(trans, CSR_HW_REV))) {
 			IWL_ERR(trans, "device not responding after resume\n");
 			iwl_trans_pcie_reset(trans, IWL_RESET_MODE_PROD_RESET);
 			return 0;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
index 56eb35d..a764c6d 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
@@ -5,6 +5,7 @@
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
  */
 #include <linux/pci.h>
+#include <linux/string_choices.h>
 #include <linux/interrupt.h>
 #include <linux/debugfs.h>
 #include <linux/sched.h>
@@ -2090,8 +2091,8 @@ static bool iwl_trans_pcie_set_product_reset(struct pci_dev *pdev, bool enable,
 						 mode);
 	if (IS_ERR(res)) {
 		IWL_DEBUG_DEV_POWER(&pdev->dev,
-				    "can't %sable product reset via DSM (%d)\n",
-				    enable ? "en" : "dis", (int)PTR_ERR(res));
+				    "can't %s product reset via DSM (%pe)\n",
+				    str_enable_disable(enable), res);
 		return false;
 	}
 
@@ -4206,7 +4207,7 @@ static void iwl_pcie_recheck_me_status(struct work_struct *wk)
 	u32 val;
 
 	val = iwl_read32(trans_pcie->trans, CSR_HW_IF_CONFIG_REG);
-	if (val != ~0U)
+	if (!PCI_POSSIBLE_ERROR(val))
 		trans_pcie->me_present = !!(val & CSR_HW_IF_CONFIG_REG_IAMT_UP);
 }
 
@@ -4228,7 +4229,7 @@ static void iwl_pcie_check_me_status(struct iwl_trans *trans)
 	/* iwl_read_prph() returns 0x5a5a5a5a if it never reached the NIC, and
 	 * that value has WIAMT_KNOWN set and WIAMT_PRESENT clear
 	 */
-	if (val != ~0U && !iwl_trans_is_hw_error_value(val) &&
+	if (!PCI_POSSIBLE_ERROR(val) && !iwl_trans_is_hw_error_value(val) &&
 	    (val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_KNOWN)) {
 		trans_pcie->me_present =
 			!!(val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_PRESENT);
@@ -4236,8 +4237,8 @@ static void iwl_pcie_check_me_status(struct iwl_trans *trans)
 	}
 
 	val = iwl_read32(trans, CSR_HW_IF_CONFIG_REG);
-	if (val != ~0U && (val & (CSR_HW_IF_CONFIG_REG_ME_OWN |
-				  CSR_HW_IF_CONFIG_REG_IAMT_UP))) {
+	if (!PCI_POSSIBLE_ERROR(val) && (val & (CSR_HW_IF_CONFIG_REG_ME_OWN |
+					       CSR_HW_IF_CONFIG_REG_IAMT_UP))) {
 		trans_pcie->me_present = 1;
 		return;
 	}
@@ -4388,6 +4389,8 @@ int iwl_pci_gen1_2_probe(struct pci_dev *pdev,
 
 	if (IS_ERR(iwl_trans->drv)) {
 		ret = PTR_ERR(iwl_trans->drv);
+		/* iwl_pcie_check_me_status() may have armed this */
+		cancel_delayed_work_sync(&trans_pcie->me_recheck_wk);
 		goto out_free_trans;
 	}
 

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-09-13 21:14 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-13 21:14 [PATCH wireless v3 0/4] wifi: iwlwifi: recover the BE200 after D3cold removes its power Navon John Lukose
2026-09-13 21:14 ` [PATCH wireless v3 1/4] wifi: iwlwifi: pcie: cancel the ME recheck work on probe failure Navon John Lukose
2026-09-13 21:14 ` [PATCH wireless v3 2/4] wifi: iwlwifi: pcie: don't infer CSME presence from a failed read Navon John Lukose
2026-09-13 21:14 ` [PATCH wireless v3 3/4] wifi: iwlwifi: pcie: deselect the product reset mode at probe Navon John Lukose
2026-09-13 21:14 ` [PATCH wireless v3 4/4] wifi: iwlwifi: pcie: recover a device that lost power in D3cold Navon John Lukose

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®