Re: [PATCH] x86/PCI: Disable D3cold on Intel BE200 Wi-Fi on Lenovo IdeaPad Pro 5 14IAH10
Nika Krasnova <[email protected]>
| Newsgroups | org.kernel.vger.linux-pci,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On Tue, 28 Jul 2026 20:14:36 +0000, "Grumbach, Emmanuel" <[email protected]> wrote: > We try to avoid resetting the firmware during suspend / resume. Out of > curiosity, can you try to reset it? I applied your hunk on top of 7.1.3, with my quirk removed, and it makes no difference. The patched and unpatched runs fail identically: iwlwifi 0000:01:00.0: timeout waiting for FW reset ACK (inta_hw=0xffffffff, reset_done 1) ieee80211 phy0: PM: dpm_run_callback(): wiphy_resume [cfg80211] returns -110 ieee80211 phy0: PM: failed to resume async: error -110 On Tue, 28 Jul 2026 15:05:59 -0500, Bjorn Helgaas <[email protected]> wrote: > I guess this means "lspci -xs01:00.0" after resume shows all 0xff? Yes. Before suspend: $ lspci -xs01:00.0 01:00.0 Network controller: Intel Corporation Wi-Fi 7(802.11be) AX1775*/AX1790*/BE20*/BE401/BE1750* 2x2 (rev 1a) 00: 86 80 2b 27 06 04 10 00 1a 00 80 02 10 00 80 00 10: 04 00 20 8c 00 00 00 00 00 00 00 00 00 00 00 00 20: 00 00 00 00 00 00 00 00 00 00 00 00 86 80 f4 00 30: 00 00 00 00 40 00 00 00 00 00 00 00 ff 01 00 00 and after resume: $ lspci -xs01:00.0 01:00.0 Network controller: Intel Corporation Wi-Fi 7(802.11be) AX1775*/AX1790*/BE20*/BE401/BE1750* 2x2 (rev 1a) 00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 10: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff I've noticed that the root port above the card also never brings the link back up: pcieport 0000:00:06.0: Data Link Layer Link Active not set in 100 msec [...] iwlwifi 0000:01:00.0: timeout waiting for FW reset ACK (inta_hw=0xffffffff, reset_done 1) ieee80211 phy0: PM: failed to resume async: error -110 0000:00:06.0 is the parent of 01:00.0. pci_pm_resume_noirq() only reaches that wait with prev_state == PCI_D3cold, so the root port itself was in D3cold, not just the endpoint. When the wait fails, everything below the port is marked disconnected. $ lspci -PP -s 01:00.0 00:06.0/01:00.0 Network controller: Intel Corporation Wi-Fi 7(802.11be) AX1775*/AX1790*/BE20*/BE401/BE1750* 2x2 (rev 1a) (The "100 msec" there is the settle delay argument rather than the wait. pcie_wait_for_link_delay() polls DLLLA for up to a second and also tries pcie_failed_link_retrain(), so a larger d3cold_delay would not help.) As far as I can tell the BE200 and its firmware are not involved. By the time iwlwifi runs, the link is already down and every read returns ones, which is what I would expect if the card never got its power back. That also explains why a module reload and a PCI remove/rescan cannot revive it: a rescan needs a working link. D3cold on this port means switching off the ACPI power resource \_SB.PC00.RP10.PXP_. I turned on the AML interpreter's method tracing (trace_debug_layer=0x80, trace_debug_level=0x10, trace_state=enable) and ran a suspend/resume where the card did not come back, to see whether the firmware's power-on sequence runs at all. Other methods interleave in the raw log, so this is grepped for RP10: Method Begin [\_SB.PC00.RP10.PXP._OFF] execution. Method Begin [\_SB.PC00.RP10.GPRS] execution. Method End [\_SB.PC00.RP10.GPRS] execution. Method Begin [\_SB.PC00.RP10.DL23] execution. Method End [\_SB.PC00.RP10.DL23] execution. Method Begin [\_SB.PC00.RP10.POFF] execution. Method Begin [\_SB.PC00.RP10.GPPR] execution. Method End [\_SB.PC00.RP10.GPPR] execution. Method End [\_SB.PC00.RP10.POFF] execution. Method End [\_SB.PC00.RP10.PXP._OFF] execution. Method Begin [\_SB.PC00.RP10.PXP._ON] execution. Method Begin [\_SB.PC00.RP10.GPRS] execution. Method End [\_SB.PC00.RP10.GPRS] execution. Method Begin [\_SB.PC00.RP10.PON] execution. Method End [\_SB.PC00.RP10.PON] execution. Method Begin [\_SB.PC00.RP10.L23D] execution. Method End [\_SB.PC00.RP10.L23D] execution. Method End [\_SB.PC00.RP10.PXP._ON] execution. The resume side mirrors the suspend side: PON() and L23D() going up, DL23() and POFF() coming down. The firmware runs the whole sequence and reports success. The link still does not train. Two registers in the port's own config space say more, both named by the ASL. L23R sits at 0xE2 bit 3; L23D writes it and then polls until the hardware clears it, and DL23 does the same with L23E on the way down. LTSM is at 0x32B, which the firmware's own debug strings call the LTSSM state. Before suspend: $ setpci -s 00:06.0 0xe2.b 11 $ for i in $(seq 5); do setpci -s 00:06.0 0x32b.b; done 40 40 40 40 40 After the failed resume: $ setpci -s 00:06.0 0xe2.b 91 $ for i in $(seq 5); do setpci -s 00:06.0 0x32b.b; done 01 01 01 01 01 L23R (0x08) is clear both times, so the request L23D makes does complete. For comparison, the sibling root port 0000:00:06.2, whose link is up: $ for i in $(seq 3); do setpci -s 00:06.2 0x32b.b; done 33 40 40 I do not know how the values in 0x32B map to LTSSM states, so the only thing I can point at is the comparison: the failing port sits in a state it never occupies while a link is up. If anyone has the decode for that register, I would like to know what 0x01 is. I can send the full acpidump output, or the decompiled DSDT and SSDTs, off-list to anyone who wants to look at PON()/POFF() and the GPRS() helper themselves. > Another thing.. Does Windows run the same suspend / resume sequence? > It also uses D3cold? I'd expect Lenovo to run thorough validation on > those flows on Windows and report possible bugs to us. I've dualbooted Windows 11 on this machine. The results: PS C:\Users\user> powercfg /a The following sleep states are available on this system: Standby (S0 Low Power Idle) Network Connected Hibernate Fast Startup The following sleep states are not available on this system: Standby (S1) The system firmware does not support this standby state. This standby state is disabled when S0 low power idle is supported. Standby (S2) The system firmware does not support this standby state. This standby state is disabled when S0 low power idle is supported. Standby (S3) The system firmware does not support this standby state. This standby state is disabled when S0 low power idle is supported. The current Device Guard configuration has disabled this standby state. Hybrid Sleep Standby (S3) is not available. The hypervisor does not support this standby state. PS C:\Users\user> powercfg /devicequery wake_armed USB4 Root Router (1.0) Intel(R) Wi-Fi 7 BE200 320MHz Output from devmgmt.msc for our BE200: Current power state: D0 Power capabilities: 00000089 PDCAP_D0_SUPPORTED PDCAP_D3_SUPPORTED PDCAP_WAKE_FROM_D3_SUPPORTED Power state mappings: S0 -> D0 S1 -> D3 S2 -> D3 S3 -> D3 S4 -> D3 S5 -> D3 The device clearly uses D3, but that does not distinguish D3hot from D3cold. Windows' DEVICE_POWER_STATE enumeration [1] bottoms out at PowerDeviceD3, and a driver does not initiate the D3hot -> D3cold step at all: it requests D3hot, and the device reaches D3cold only when the bus driver or the system firmware removes the power source [2]. So what Device Manager reports is the requested D-state, not whether the rail was subsequently removed. This machine also sleeps via S0 Low Power Idle rather than S3, so the Sx -> Dx table above does not even describe the flow that matters here. Entering D3cold while the system stays in S0 has to be enabled by the power policy owner, through the INF or a SetD3ColdSupport() call [2]. Does the Windows BE200 driver enable D3cold transitions in S0 on platforms like this one? If it does not, then Windows never takes the card below D3hot here, and the D3cold->D0 path would never have been exercised in validation. Given that the failure is at the link layer above the device rather than in the device itself, this should probably be a PCI quirk in drivers/pci/quirks.c instead of arch/x86/pci/fixup.c. [1] https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ne-wdm-_device_power_state [2] https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/enabling-transitions-to-d3cold -- Nika Krasnova