From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Ping-Ke Shih <pkshih@realtek.com>,
Oleksandr Havrylov <goainwo@gmail.com>,
Sasha Levin <sashal@kernel.org>,
linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 7.0-6.18] wifi: rtw88: add quirks to disable PCI ASPM and deep LPS for HP P3S95EA#ACB
Date: Mon, 20 Apr 2026 09:16:50 -0400 [thread overview]
Message-ID: <20260420132314.1023554-16-sashal@kernel.org> (raw)
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>
From: Ping-Ke Shih <pkshih@realtek.com>
[ Upstream commit b2bf9d61e14af4129362aeb9c10034229a6d8f08 ]
On an HP laptop (P3S95EA#ACB) equipped with a Realtek RTL8821CE 802.11ac
PCIe adapter (PCI ID: 10ec:c821), the system experiences a hard lockup
(complete freeze of the UI and kernel, sysrq doesn't work, requires
holding the power button) when the WiFi adapter enters the power
saving state. Disable PCI ASPM to avoid system freeze.
In addition, driver throws messages periodically. Though this doesn't
always cause unstable connection, missing H2C commands might cause
unpredictable results. Disable deep LPS to avoid this as well.
rtw88_8821ce 0000:13:00.0: firmware failed to leave lps state
rtw88_8821ce 0000:13:00.0: failed to send h2c command
rtw88_8821ce 0000:13:00.0: failed to send h2c command
Tested on HP Notebook P3S95EA#ACB (kernel 6.19.7-1-cachyos):
- No hard freeze observed during idle or active usage.
- Zero h2c or lps errors in dmesg across idle (10 min),
load stress (100MB download), and suspend/resume cycle.
- Both quirk flags confirmed active via sysfs without any
manual modprobe parameters.
Reported-by: Oleksandr Havrylov <goainwo@gmail.com>
Closes: https://lore.kernel.org/linux-wireless/CALdGYqSQ1Ko2TTBhUizMu_FvLMUAuQfFrVwS10n_C-LSQJQQkQ@mail.gmail.com/
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Tested-by: Oleksandr Havrylov <goainwo@gmail.com>
Link: https://patch.msgid.link/20260316035635.16550-1-pkshih@realtek.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Now I have all the information I need. Let me compile my analysis.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject Line
**Record:** [wifi: rtw88] [add quirks] [Adds DMI-based quirks to disable
PCI ASPM and deep LPS for a specific HP laptop model]
### Step 1.2: Tags
- **Reported-by:** Oleksandr Havrylov <goainwo@gmail.com> — a real user
reporting the bug
- **Closes:** lore.kernel.org link to original bug report
- **Signed-off-by:** Ping-Ke Shih <pkshih@realtek.com> — Realtek's rtw88
maintainer
- **Tested-by:** Oleksandr Havrylov <goainwo@gmail.com> — reporter
confirmed the fix works
- **Link:** patch.msgid.link for the submission
No Fixes: tag (expected for this type of quirk addition). No Cc: stable
(expected). Author is the rtw88 subsystem maintainer.
### Step 1.3: Commit Body Analysis
- **Bug:** HP laptop (P3S95EA#ACB) with RTL8821CE WiFi experiences
**hard lockup** (complete system freeze, SysRq unresponsive, requires
power button) when WiFi adapter enters power saving state
- **Secondary issue:** Firmware error messages ("failed to leave lps
state", "failed to send h2c command") suggesting broken power
management communication
- **Testing evidence:** Detailed test plan with idle, load, and
suspend/resume validation on 6.19.7 kernel
- **Failure mode:** CRITICAL — hard lockup requiring power cycle
### Step 1.4: Hidden Bug Fix Detection
**Record:** This is NOT a hidden bug fix — it's an explicit hardware
quirk/workaround for a specific device that causes system-wide hard
lockups. This falls squarely into the "hardware quirk" exception
category for stable.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
- `main.h`: +5 lines — new enum `rtw_quirk_dis_caps` with 2 values
- `pci.c`: +31 lines — DMI include, callback function, quirk table,
`dmi_check_system()` call
- Total: **+36 lines, 0 removed**
- Functions modified: `rtw_pci_probe()` (1 line added). New:
`rtw_pci_disable_caps()` callback
- Scope: Single-driver, self-contained
### Step 2.2: Code Flow Change
1. New enum provides named constants for quirk capability bits
2. `rtw_pci_disable_caps()`: DMI callback that sets
`rtw_pci_disable_aspm` and/or `rtw_disable_lps_deep_mode` global
bools to true based on bitmask in driver_data
3. `rtw_pci_quirks[]`: DMI table matching HP vendor + "HP Notebook"
product + "P3S95EA#ACB" SKU
4. `dmi_check_system()` call added in `rtw_pci_probe()` before
`rtw_core_init()`, so quirks are set before driver initialization
uses those globals
### Step 2.3: Bug Mechanism
**Category: Hardware workaround (DMI quirk)**
- The quirk sets the same module-level bools (`rtw_pci_disable_aspm`,
`rtw_disable_lps_deep_mode`) that existing module parameters expose
- These bools are already checked in `rtw_pci_clkreq_set()`,
`rtw_pci_aspm_set()`, and `rtw_update_lps_deep_mode()`
- The mechanism simply automates what a user would do with `modprobe
rtw88_pci disable_aspm=Y` + `rtw88_core disable_lps_deep=Y`
### Step 2.4: Fix Quality
- **Obviously correct:** Uses standard DMI matching infrastructure. Sets
existing, well-tested booleans. The same mechanism already works via
module parameters.
- **Minimal and surgical:** Only affects the specific HP laptop model
with the matching DMI strings. No behavioral change for any other
system.
- **Regression risk:** Essentially zero — only changes behavior on one
specific laptop, and only disables power saving features that cause
lockups on that device.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
- `rtw_pci_disable_aspm` introduced by commit `68aa716b7dd36f`
(2020-07-15) — present since ~v5.9
- `rtw_disable_lps_deep_mode` introduced by commit `fc3ac64a3a2868`
(2020-10-30) — present since ~v5.10
- Both variables are available in ALL active stable trees
### Step 3.2: No Fixes tag — N/A
### Step 3.3: File History
The pci.c file is moderately active. The eb101d2abdccc commit (upstream
bridge check) touches a different part of the file and does NOT conflict
with this patch. The quirk insertion point (after `rtw_pci_err_handler`
export and before `rtw_pci_probe`) and the `dmi_check_system()`
insertion point (in `rtw_pci_probe` before `rtw_core_init`) are both
clean in the current v7.0 tree.
### Step 3.4: Author
Ping-Ke Shih (pkshih@realtek.com) is the **rtw88 subsystem maintainer**
at Realtek. He maintains the rtw tree and has many commits across the
rtw88 codebase.
### Step 3.5: Dependencies
- The patch is **fully standalone** — no prerequisites needed
- It only references existing global variables and standard kernel DMI
infrastructure
- The enum addition in main.h is self-contained
---
## PHASE 4: MAILING LIST RESEARCH
### Step 4.1: Original Discussion
- b4 dig found the submission at
`20260316035635.16550-1-pkshih@realtek.com`
- Only v1 — no revisions needed. Clean acceptance.
- Thread from mbox: The reporter (Oleksandr Havrylov) provided detailed
Tested-by with positive results.
- Maintainer (Ping-Ke Shih) acknowledged the test and added Tested-by to
the commit message.
### Step 4.2: Reviewers
- linux-wireless@vger.kernel.org was CC'd
- Reporter provided Tested-by — direct confirmation the fix works
### Step 4.3: Bug Report
- Closes link points to the original bug report email from the user
- Single reporter but the issue is deterministic: hard lockup when WiFi
enters power saving
### Step 4.4: Series Context
- Single standalone patch, not part of a series
### Step 4.5: Stable Discussion
- No specific stable discussion found. No Cc: stable on the original
patch.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Functions
- `rtw_pci_disable_caps()` — new callback, only called by
`dmi_check_system()`
- `rtw_pci_probe()` — modified to call `dmi_check_system()`
### Step 5.2: Callers
- `rtw_pci_probe()` is the PCI probe function called for every rtw88
PCIe device during driver loading — common path
- `rtw_pci_disable_aspm` is checked in `rtw_pci_clkreq_set()` and
`rtw_pci_aspm_set()` — called during power state transitions
- `rtw_disable_lps_deep_mode` is checked in `rtw_update_lps_deep_mode()`
— called during firmware init
### Step 5.3-5.5: Call Chain
The quirk only sets global booleans that are already checked in existing
code paths. No new logic branches introduced.
---
## PHASE 6: STABLE TREE ANALYSIS
### Step 6.1: Code Exists in Stable
- `rtw_pci_disable_aspm` exists since v5.9 (commit 68aa716b7dd36f)
- `rtw_disable_lps_deep_mode` exists since v5.10 (commit fc3ac64a3a2868)
- The RTL8821CE driver exists in all active stable trees
- **The buggy behavior exists in all stable trees supporting this
hardware**
### Step 6.2: Backport Complications
- The patch should apply cleanly or with minimal offset to all active
stable trees
- The insertion points (after EXPORT_SYMBOL, before probe function,
inside probe) are stable
- No conflicting structural changes in this area
### Step 6.3: No related fixes already in stable for this specific
laptop
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem
- **drivers/net/wireless/realtek/rtw88** — WiFi driver for Realtek
chipsets
- **Criticality: IMPORTANT** — RTL8821CE is a widely-used WiFi adapter
in consumer laptops
- RTW88 is an active, well-maintained in-tree driver
### Step 7.2: Activity
- Actively maintained by Realtek engineers (Ping-Ke Shih is the
maintainer)
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Affected Users
- Users of the specific HP laptop model (P3S95EA#ACB) with RTL8821CE
WiFi adapter
- DMI matching is narrowly scoped (vendor + product + SKU)
### Step 8.2: Trigger Conditions
- **Trigger:** WiFi adapter enters power saving state — this happens
automatically during normal idle usage
- **Frequency:** Very common — happens during any period of idle WiFi
usage
- **Deterministic:** The lockup is reproducible
### Step 8.3: Failure Mode Severity
- **Hard lockup** — system completely freezes, SysRq unresponsive,
requires holding power button
- **Severity: CRITICAL** — total system unavailability, potential data
loss from unclean shutdown
### Step 8.4: Risk-Benefit
- **Benefit: HIGH** — prevents deterministic hard lockups on affected
hardware
- **Risk: VERY LOW** — only affects one specific laptop model; uses
existing, well-tested disable mechanisms; is functionally identical to
module parameters that already exist
- **Ratio: Excellent** — high benefit, near-zero regression risk
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence Compilation
**FOR backporting:**
- Fixes deterministic hard lockups (CRITICAL severity)
- Small, self-contained change (+36 lines, single driver)
- Written by the subsystem maintainer (Ping-Ke Shih at Realtek)
- Tested and confirmed working by the reporter
- Uses standard DMI quirk pattern already used in other drivers (ath9k,
etc.)
- Only automates existing module parameter functionality
- Zero regression risk for non-affected systems (narrow DMI match)
- The underlying infrastructure (module params) exists in all stable
trees since v5.10
- Hardware quirk = explicitly allowed exception for stable
**AGAINST backporting:**
- No explicit Cc: stable (expected — that's why we're reviewing it)
- Adds new code rather than modifying existing code (but this is
inherent to quirk additions)
### Step 9.2: Stable Rules Checklist
1. **Obviously correct and tested?** YES — uses standard DMI matching,
confirmed by Tested-by
2. **Fixes a real bug?** YES — hard lockup reported and reproduced by a
user
3. **Important issue?** YES — CRITICAL: hard lockup requiring power
cycle
4. **Small and contained?** YES — 36 lines, 2 files, single driver
5. **No new features?** YES — disables power features that cause
lockups; no new user-visible behavior
6. **Can apply to stable?** YES — clean, standalone, no dependencies
### Step 9.3: Exception Category
**Hardware quirk/workaround** — DMI-based quirk to disable broken power
management on specific hardware. This is an explicitly allowed exception
for stable trees.
---
## Verification
- [Phase 1] Parsed tags: Reported-by from real user, Tested-by from same
user, author is rtw88 maintainer
- [Phase 2] Diff: +36 lines across 2 files (main.h enum + pci.c DMI
table + probe call), no code removed
- [Phase 3] git blame: `rtw_pci_disable_aspm` from 68aa716b7dd36f
(2020-07-15), `rtw_disable_lps_deep_mode` from fc3ac64a3a2868
(2020-10-30) — both present in all active stable trees
- [Phase 3] git log: no dependencies identified; eb101d2abdccc touches
different code area
- [Phase 4] b4 dig -c b2bf9d61e14af: found at
https://patch.msgid.link/20260316035635.16550-1-pkshih@realtek.com
- [Phase 4] b4 dig -a: only v1, clean acceptance with no revisions
- [Phase 4] b4 dig -w: linux-wireless list and reporter CC'd
- [Phase 4] mbox: reporter confirmed fix with detailed test (idle, load,
suspend/resume)
- [Phase 5] `rtw_pci_disable_aspm` checked in `rtw_pci_clkreq_set()` and
`rtw_pci_aspm_set()`; `rtw_disable_lps_deep_mode` checked in
`rtw_update_lps_deep_mode()` — all existing code paths
- [Phase 6] Code infrastructure exists in all active stable trees
(v5.10+), patch is standalone
- [Phase 6] Diff against v7.0 shows clean insertion points with no
conflicts
- [Phase 7] ath9k uses identical `dmi_check_system` quirk pattern,
establishing precedent
- [Phase 8] Failure mode: hard lockup (CRITICAL), triggers during normal
idle WiFi usage
**YES** — This is a textbook hardware quirk that prevents deterministic
hard lockups on specific hardware. It uses standard DMI matching
infrastructure, is written by the subsystem maintainer, tested by the
reporter, adds only 36 lines, has zero regression risk for unaffected
systems, and the underlying mechanism already exists in all stable
trees.
**YES**
drivers/net/wireless/realtek/rtw88/main.h | 5 ++++
drivers/net/wireless/realtek/rtw88/pci.c | 31 +++++++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 1ab70214ce36e..55b794d4584c4 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -432,6 +432,11 @@ enum rtw_wow_flags {
RTW_WOW_FLAG_MAX,
};
+enum rtw_quirk_dis_caps {
+ QUIRK_DIS_CAP_PCI_ASPM,
+ QUIRK_DIS_CAP_LPS_DEEP,
+};
+
/* the power index is represented by differences, which cck-1s & ht40-1s are
* the base values, so for 1s's differences, there are only ht20 & ofdm
*/
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index 56b16186d3aa4..ca26e0a7f538f 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -2,6 +2,7 @@
/* Copyright(c) 2018-2019 Realtek Corporation
*/
+#include <linux/dmi.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "main.h"
@@ -1744,6 +1745,34 @@ const struct pci_error_handlers rtw_pci_err_handler = {
};
EXPORT_SYMBOL(rtw_pci_err_handler);
+static int rtw_pci_disable_caps(const struct dmi_system_id *dmi)
+{
+ uintptr_t dis_caps = (uintptr_t)dmi->driver_data;
+
+ if (dis_caps & BIT(QUIRK_DIS_CAP_PCI_ASPM))
+ rtw_pci_disable_aspm = true;
+
+ if (dis_caps & BIT(QUIRK_DIS_CAP_LPS_DEEP))
+ rtw_disable_lps_deep_mode = true;
+
+ return 1;
+}
+
+static const struct dmi_system_id rtw_pci_quirks[] = {
+ {
+ .callback = rtw_pci_disable_caps,
+ .ident = "HP Notebook - P3S95EA#ACB",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Notebook"),
+ DMI_MATCH(DMI_PRODUCT_SKU, "P3S95EA#ACB"),
+ },
+ .driver_data = (void *)(BIT(QUIRK_DIS_CAP_PCI_ASPM) |
+ BIT(QUIRK_DIS_CAP_LPS_DEEP)),
+ },
+ {}
+};
+
int rtw_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@@ -1771,6 +1800,8 @@ int rtw_pci_probe(struct pci_dev *pdev,
rtwpci = (struct rtw_pci *)rtwdev->priv;
atomic_set(&rtwpci->link_usage, 1);
+ dmi_check_system(rtw_pci_quirks);
+
ret = rtw_core_init(rtwdev);
if (ret)
goto err_release_hw;
--
2.53.0
next prev parent reply other threads:[~2026-04-20 13:23 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260420132314.1023554-1-sashal@kernel.org>
2026-04-20 13:16 ` [PATCH AUTOSEL 7.0-6.18] wifi: ath12k: Fix the assignment of logical link index Sasha Levin
2026-04-20 13:16 ` [PATCH AUTOSEL 7.0-6.12] wifi: rtw89: ser: Wi-Fi 7 reset HALT C2H after reading it Sasha Levin
2026-04-20 13:16 ` [PATCH AUTOSEL 7.0-5.10] wifi: rsi_91x_usb: do not pause rfkill polling when stopping mac80211 Sasha Levin
2026-04-20 13:16 ` Sasha Levin [this message]
2026-04-20 13:16 ` [PATCH AUTOSEL 6.18] wifi: brcmfmac: validate bsscfg indices in IF events Sasha Levin
2026-04-20 13:17 ` [PATCH AUTOSEL 7.0-6.6] wifi: mac80211: set band information only for non-MLD when probing stations using NULL frame Sasha Levin
2026-04-20 13:17 ` [PATCH AUTOSEL 7.0-6.19] wifi: mt76: avoid to set ACK for MCU command if wait_resp is not set Sasha Levin
2026-04-20 13:17 ` [PATCH AUTOSEL 7.0-6.19] wifi: rtw89: Add support for TP-Link Archer TX50U Sasha Levin
2026-04-20 13:17 ` [PATCH AUTOSEL 7.0-6.1] wifi: mac80211: use ap_addr for 4-address NULL frame destination Sasha Levin
2026-04-20 13:17 ` [PATCH AUTOSEL 7.0-6.18] wifi: ath12k: Set up MLO after SSR Sasha Levin
2026-04-20 13:18 ` [PATCH AUTOSEL 7.0-6.18] wifi: iwlwifi: mld: always assign a fw id to a vif Sasha Levin
2026-04-20 13:18 ` [PATCH AUTOSEL 6.18] wifi: wl1251: validate packet IDs before indexing tx_frames Sasha Levin
2026-04-20 13:18 ` [PATCH AUTOSEL 7.0-6.18] wifi: mt76: flush pending TX before channel switch Sasha Levin
2026-04-20 13:18 ` [PATCH AUTOSEL 7.0-6.6] wifi: mt76: fix list corruption in mt76_wcid_cleanup Sasha Levin
2026-04-20 13:18 ` [PATCH AUTOSEL 7.0-6.12] wifi: mt76: add missing lock protection in mt76_sta_state for sta_event callback Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.18] wifi: mt76: mt7996: Disable Rx hdr_trans in monitor mode Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.18] wifi: iwlwifi: restrict TOP reset to some devices Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.12] wifi: mt76: mt7925: Skip scan process during suspend Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-5.10] wifi: mt76: mt76x02: wake queues after reconfig Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.12] wifi: mt76: mt7925: resolve link after acquiring mt76 mutex Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.19] wifi: rtw89: mac: remove A-die off setting for RTL8852C and RTL8922A Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.18] wifi: mt76: mt7996: fix queue pause after scan due to wrong channel switch reason Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.18] wifi: brcmfmac: of: defer probe for MAC address Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.19] wifi: rtw89: Add support for Buffalo WI-U3-2400XE2 Sasha Levin
2026-04-20 13:20 ` [PATCH AUTOSEL 7.0-6.19] wifi: rtw89: Add support for Elecom WDC-XE2402TU3-B Sasha Levin
2026-04-20 13:20 ` [PATCH AUTOSEL 7.0-6.6] wifi: mt76: mt7996: reset device after MCU message timeout Sasha Levin
2026-04-20 13:21 ` [PATCH AUTOSEL 7.0-5.10] wifi: rtw88: TX QOS Null data the same way as Null data Sasha Levin
2026-04-20 13:21 ` [PATCH AUTOSEL 7.0-6.18] wifi: rtw88: validate RX rate to prevent out-of-bound Sasha Levin
2026-04-20 13:21 ` [PATCH AUTOSEL 7.0-6.18] wifi: ath12k: Skip adding inactive partner vdev info Sasha Levin
2026-04-20 13:21 ` [PATCH AUTOSEL 7.0-6.18] wifi: mt76: mt7996: fix frequency separation for station STR mode Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260420132314.1023554-16-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=goainwo@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=patches@lists.linux.dev \
--cc=pkshih@realtek.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox