* [PATCH wireless 0/2] wifi: iwlwifi: recover the device after it loses power in D3cold
@ 2026-08-29 9:54 Navon John Lukose
2026-08-29 9:54 ` [PATCH wireless 1/2] wifi: iwlwifi: pcie: arm the product reset at probe Navon John Lukose
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Navon John Lukose @ 2026-08-29 9:54 UTC (permalink / raw)
To: miriam.rachel.korenblit, linux-wireless
Cc: nika, emmanuel.grumbach, helgaas, markpearson, linux-pci,
linux-kernel, stable, Navon John Lukose
On several Meteor Lake laptops the Intel BE200 does not survive a D3cold
transition: the platform's _PR3 power resource genuinely removes the M.2
module's rail, and the card does not restart when the rail and PERST# are
restored. Config space reads 0xffffffff, the link never trains, and the
device stays gone until a reboot.
iwlwifi already has everything needed to recover it. The platform-level
device reset walks _PRR and evaluates _RST, and the vendor _DSM that arms
it is already spoken. The problem is ordering: arming happens from the
removal path, by which point the device no longer answers, and the _DSM is
gated on the firmware reading the device's PCI ID back out of config
space. So arming can never succeed at the one moment it matters.
Patch 1 arms it at probe, while the device still answers. Patch 2 asks for
a product reset when the device is not on the bus after resume, instead of
re-initialising hardware that is not there.
Analysis, register dumps and the discussion this came out of:
Link: https://lore.kernel.org/all/20260829093922.37103-1-navonjohnlukose@gmail.com/
Tested on a Lenovo Yoga Pro 7 14IAH10 (BIOS QGCN35WW), BE200
SUBSYS_00F48086: the card dies in D3cold on every s2idle exactly as
before, and recovers on its own in about 5s, repeatedly, with wifi both
connected and idle at suspend time. With the reset skipped but everything
else identical it stays absent, so the reset is what recovers it rather
than the remove/rescan.
Caveats: one machine and one BIOS, discrete (!integrated) path only - I
have no CNVi hardware, so the integrated arming mask is untested.
Recovery costs ~4.3s of Sleep() inside the platform's _RST, which is
firmware and not something we can shorten.
Tagged for stable: the PLDR path has never worked on platforms with this
_DSM gate, and both changes are small and self-limiting - every _RST
evaluation is already preceded by set_product_reset() setting the mode
that reset wants, so arming at probe cannot alter the behaviour of any
later reset.
Signed-off-by: Navon John Lukose <navonjohnlukose@gmail.com>
Navon John Lukose (2):
wifi: iwlwifi: pcie: arm the product reset at probe
wifi: iwlwifi: pcie: request a product reset when the device is gone
after resume
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 12 ++++++++++++
drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c | 5 +++++
2 files changed, 17 insertions(+)
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH wireless 1/2] wifi: iwlwifi: pcie: arm the product reset at probe
2026-08-29 9:54 [PATCH wireless 0/2] wifi: iwlwifi: recover the device after it loses power in D3cold Navon John Lukose
@ 2026-08-29 9:54 ` Navon John Lukose
2026-08-29 9:54 ` [PATCH wireless 2/2] wifi: iwlwifi: pcie: request a product reset when the device is gone after resume Navon John Lukose
[not found] ` <20260829100758.8E8491F000E9@smtp.kernel.org>
2 siblings, 0 replies; 4+ messages in thread
From: Navon John Lukose @ 2026-08-29 9:54 UTC (permalink / raw)
To: miriam.rachel.korenblit, linux-wireless
Cc: nika, emmanuel.grumbach, helgaas, markpearson, linux-pci,
linux-kernel, stable, Navon John Lukose
The driver already implements the platform-level device reset (PLDR):
iwl_trans_pcie_call_reset() walks _PRR and evaluates _RST, and
iwl_trans_pcie_set_product_reset() arms it over the vendor _DSM. But it
is armed too late to ever help.
set_product_reset() is only called from iwl_trans_pcie_removal_wk(),
i.e. once the device is already being torn down. On these platforms the
_DSM dispatch is gated on the firmware reading the device's PCI ID back
out of config space:
Method (WIST) { Switch (ToInteger (VDID)) { Case (0x272B8086) {...} } }
If the device has lost power VDID reads 0xffffffff, WIST() returns 0,
the _DSM never reaches the vendor functions and acpi_check_dsm() fails:
scheduling reset (mode=6)
ACPI _DSM not available (-19), cannot do product reset
So the reset stays disarmed, _RST falls back to a plain function-level
reset and the device is unrecoverable in exactly the case PLDR exists
for. Observed on Intel BE200 (8086:272b) on Meteor Lake laptops, where a
D3cold transition removes the M.2 module's power rail and the card does
not restart when the rail and PERST# are restored.
Arm it during probe instead, while the device still answers. The mode is
sticky in the platform's namespace, so it is still set when the device
later disappears. _RST is only evaluated when the driver actually asks
for a reset, and a subsequent non-product reset re-runs the existing
disarm path as before. On platforms with no such _DSM this is a no-op.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=221695
Fixes: 9673c35486d4 ("wifi: iwlwifi: implement product reset for TOP errors")
Cc: stable@vger.kernel.org
Signed-off-by: Navon John Lukose <navonjohnlukose@gmail.com>
---
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
@@ -4252,6 +4252,11 @@
iwl_trans_pcie_check_product_reset_status(pdev);
iwl_trans_pcie_check_product_reset_mode(pdev);
+ /* must be armed while the device still answers: the _DSM is gated on
+ * reading its PCI ID out of config space
+ */
+ iwl_trans_pcie_set_product_reset(pdev, true, mac_cfg->integrated);
+
/* set the things we know so far for the grab NIC access */
iwl_trans_set_info(iwl_trans, &info);
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH wireless 2/2] wifi: iwlwifi: pcie: request a product reset when the device is gone after resume
2026-08-29 9:54 [PATCH wireless 0/2] wifi: iwlwifi: recover the device after it loses power in D3cold Navon John Lukose
2026-08-29 9:54 ` [PATCH wireless 1/2] wifi: iwlwifi: pcie: arm the product reset at probe Navon John Lukose
@ 2026-08-29 9:54 ` Navon John Lukose
[not found] ` <20260829100758.8E8491F000E9@smtp.kernel.org>
2 siblings, 0 replies; 4+ messages in thread
From: Navon John Lukose @ 2026-08-29 9:54 UTC (permalink / raw)
To: miriam.rachel.korenblit, linux-wireless
Cc: nika, emmanuel.grumbach, helgaas, markpearson, linux-pci,
linux-kernel, stable, Navon John Lukose
On platforms where D3cold removes the WiFi module's power rail, the
device can come back from suspend completely absent from the bus: config
space reads 0xffffffff and the downstream link never trains.
_iwl_pci_resume() currently notices only a subset of this (scratch ==
~0U, and only when the device was enabled), then "hopes for the best" by
re-initialising over PCI, which cannot work - the hardware is not there.
The result is several seconds of handshake timeouts and a bogus
ADVANCED_SYSASSERT dump before giving up, and the device stays gone
until reboot.
Check whether the device answers config cycles at all, and if not ask
for a product reset, which power-cycles the module and re-enumerates it.
The check is deliberately placed before the STATUS_DEVICE_ENABLED block:
that block is skipped entirely when the device was idle or down at
suspend time, which is a common case (e.g. the radio was switched off)
and one where the device is just as dead.
Fixes: 9673c35486d4 ("wifi: iwlwifi: implement product reset for TOP errors")
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221695
Cc: stable@vger.kernel.org
Signed-off-by: Navon John Lukose <navonjohnlukose@gmail.com>
---
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -1232,6 +1232,18 @@
if (!trans->op_mode)
return 0;
+ /* Not answering config cycles: it fell off the bus and will not come
+ * back from a PCI-level re-init. Deliberately checked before the
+ * STATUS_DEVICE_ENABLED block below, which is skipped entirely if the
+ * device was idle or down when we suspended.
+ */
+ if (!pci_device_is_present(pdev)) {
+ IWL_ERR(trans,
+ "device is not on the bus after resume, requesting product reset\n");
+ iwl_trans_pcie_reset(trans, IWL_RESET_MODE_PROD_RESET);
+ return 0;
+ }
+
if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
/*
* Scratch value was altered, this means the device was powered
^ permalink raw reply [flat|nested] 4+ messages in thread[parent not found: <20260829100758.8E8491F000E9@smtp.kernel.org>]
* Re: [PATCH wireless 1/2] wifi: iwlwifi: pcie: arm the product reset at probe
[not found] ` <20260829100758.8E8491F000E9@smtp.kernel.org>
@ 2026-08-29 12:37 ` Navon John Lukose
0 siblings, 0 replies; 4+ messages in thread
From: Navon John Lukose @ 2026-08-29 12:37 UTC (permalink / raw)
To: linux-wireless, miriam.rachel.korenblit
Cc: nika, emmanuel.grumbach, helgaas, linux-pci, linux-kernel,
Navon John Lukose, stable
Both findings are correct. Please drop this series; a v2 is coming.
On the first: arming at probe does leave the mode selected for the
lifetime of the driver, and the disarm in iwl_trans_pcie_removal_wk()
cannot be relied on to undo it, because it fails in exactly the case
that matters - the DSM is gated on the platform reading the device's
PCI ID out of config space, so it is unavailable once the device is off
the bus, and set_product_reset() ignores that failure when disarming.
_RST is not gated the same way: it reads the mode variable directly, so
a stale selection does execute a full product reset, Bluetooth off/on
included, with no BT teardown and with the ME downgrade bypassed.
I also need to retract something. The cover letter argued for stable on
the grounds that "every _RST evaluation is already preceded by
set_product_reset() setting the mode that reset wants, so arming at
probe cannot alter the behaviour of any later reset". That is wrong. It
holds only when the disarm succeeds, and the disarm cannot succeed on a
device that is gone. The backport rationale as written does not stand.
On the second: yes, it logs IWL_ERR on every probe on any platform
without this DSM, and the commit message's claim that it is a no-op
there is wrong. The two neighbouring functions,
iwl_trans_pcie_check_product_reset_mode() and _status(), already return
silently in the same situation, so the asymmetry looks unintended - and
it is what hid the failed disarm above.
v2 will instead select the mode from the suspend callback and clear it
on resume, so it is only selected across the suspend window; guard the
_RST call with pci_device_is_present(), which reads the same config
register the platform's own gate does; and demote the log.
Unrelated, but found while checking this: iwl_pcie_recheck_me_status()
reads CSR_HW_IF_CONFIG_REG without a liveness check, so on a device that
is off the bus it sees 0xffffffff, concludes IAMT_UP is set, and marks
ME present on a machine that has none - which then downgrades every
later product reset. I will send that separately.
Patch 2/2 is substantively unchanged in v2.
Thanks for the review.
Navon
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-29 12:37 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-29 9:54 [PATCH wireless 0/2] wifi: iwlwifi: recover the device after it loses power in D3cold Navon John Lukose
2026-08-29 9:54 ` [PATCH wireless 1/2] wifi: iwlwifi: pcie: arm the product reset at probe Navon John Lukose
2026-08-29 9:54 ` [PATCH wireless 2/2] wifi: iwlwifi: pcie: request a product reset when the device is gone after resume Navon John Lukose
[not found] ` <20260829100758.8E8491F000E9@smtp.kernel.org>
2026-08-29 12:37 ` [PATCH wireless 1/2] wifi: iwlwifi: pcie: arm the product reset at probe 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®