* [PATCH AUTOSEL 6.18-5.10] ata: ahci: fail probe if BAR too small for claimed ports
[not found] <20260831133314.4125787-1-sashal@kernel.org>
@ 2026-08-31 13:23 ` Sasha Levin
2026-08-31 14:46 ` sashiko-bot
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.12] ata: libata-core: Disable LPM on some WD drives Sasha Levin
` (3 subsequent siblings)
4 siblings, 1 reply; 7+ messages in thread
From: Sasha Levin @ 2026-08-31 13:23 UTC (permalink / raw)
To: patches, stable
Cc: liyouhong, Damien Le Moal, Niklas Cassel, Sasha Levin, linux-ide,
linux-kernel
From: liyouhong <liyouhong@kylinos.cn>
[ Upstream commit c4086c6e1af757e1ff26fa2d2926b3ec0195de79 ]
When an AHCI controller is disabled in BIOS, its HOST_CAP register may
contain a bogus value, e.g. 0xFFFFFFFF.
Since CAP.NP (Number of Ports) is a zeroes based 5-bit register field,
a value of 0x1f means 32 ports. If CAP.NP claims more ports than can
physically fit within the mapped BAR region, accessing port registers
beyond the BAR boundary causes a kernel panic.
Add validation in ahci_init_one() to check that the BAR size is
sufficient for the number of ports claimed in CAP.NP. The check
calculates the required MMIO size as:
required_size = 0x100 (global registers) + max_ports * 0x80
If required_size exceeds the actual BAR size, the probe fails with
-ENODEV, preventing the panic and providing a clear error message.
Reported-by: liyouhong <liyouhong@kylinos.cn>
Closes: https://lore.kernel.org/all/20260422080322.1006592-1-dayou5941@163.com/
Suggested-by: Damien Le Moal <dlemoal@kernel.org>
Suggested-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: liyouhong <liyouhong@kylinos.cn>
[cassel: commit log]
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
# Stable Backport Analysis: `ata: ahci: fail probe if BAR too small for
claimed ports`
**Local tree:** Linux **6.18.44** (`git describe HEAD` → `v6.18.44`)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[ata: ahci]` `[fail]` — Fail AHCI PCI probe when the mapped
BAR is smaller than the MMIO space required by the port count claimed in
`HOST_CAP.NP`.
### Step 1.2: Tags
**Record:**
- **Reported-by:** liyouhong \<liyouhong@kylinos.cn\> — real-world
reporter (Kylin OS)
- **Closes:** https://lore.kernel.org/all/20260422080322.1006592-1-
dayou5941@163.com/ — original bug report thread
- **Suggested-by:** Damien Le Moal \<dlemoal@kernel.org\>, Niklas Cassel
\<cassel@kernel.org\>
- **Reviewed-by:** Damien Le Moal \<dlemoal@kernel.org\> — libata
maintainer review
- **Signed-off-by:** liyouhong, Niklas Cassel
- No `Fixes:`, no `Cc: stable@vger.kernel.org` (expected for manual
review)
- No syzbot / sanitizer tags
### Step 1.3: Body analysis
**Record:**
- **Bug:** When an AHCI controller is disabled in BIOS, `HOST_CAP` can
read as `0xFFFFFFFF`. `CAP.NP` (5-bit, zero-based) then reports 32
ports. The driver later accesses per-port MMIO at `0x100 + port *
0x80`, which can extend past the actual BAR → **kernel panic**.
- **Symptom:** Kernel panic during AHCI probe (boot-time PCI
enumeration).
- **Root cause:** No validation that BAR size can accommodate all ports
implied by `CAP.NP`.
- **Fix:** In `ahci_init_one()`, after `pcim_iomap()`, compute
`required_size = 0x100 + max_ports * 0x80`; if it exceeds
`pci_resource_len()`, return `-ENODEV` with a warning.
### Step 1.4: Hidden bug fix?
**Record:** Not disguised — this is an explicit crash-prevention fix,
not cleanup or optimization.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- **Files:** `drivers/ata/ahci.c` only (+22 / -0)
- **Functions:** New `ahci_validate_bar_size()`; call added in
`ahci_init_one()`
- **Scope:** Single-file, surgical fix
### Step 2.2: Code flow change
**Record:**
- **Hunk 1 (new function):** After MMIO mapping, read `HOST_CAP`, derive
`max_ports` via `ahci_nr_ports()`, compute `last_port_end = 0x100 +
max_ports * 0x80`, compare to `pci_resource_len()`. Return `-ENODEV`
if BAR is too small.
- **Hunk 2 (`ahci_init_one`):** Call validation immediately after
`pcim_iomap()`, before `ahci_remap_check()` and
`ahci_pci_save_initial_config()`.
- **Path affected:** PCI probe initialization path (normal boot, not
error recovery).
### Step 2.3: Bug mechanism
**Record:** **Buffer overflow / out-of-bounds MMIO access.** Bogus
`CAP.NP` causes the driver to touch port register space beyond the
mapped BAR. Downstream accessors like `__ahci_port_base()` and
`readl(port_mmio + PORT_CMD)` in `ahci_save_initial_config()` and
`ahci_mark_external_port()` can panic.
### Step 2.4: Fix quality
**Record:**
- **Obviously correct:** Matches AHCI register layout (`0x100` global +
`0x80` per port); uses existing `ahci_nr_ports()` helper.
- **Minimal:** 22 lines, no unrelated changes.
- **Regression risk:** Very low. Legitimate controllers have BARs sized
for their port count; only broken/disabled configurations are
rejected.
- **False negative risk:** A controller with bogus `CAP` but a large
enough BAR could still probe; that is not worse than today and is
outside this patch’s scope.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:** `pcim_iomap()` at lines 1987–1989 last touched by
`bdcddd0cdc39d` (Oct 2024, PCI deprecation cleanup). The missing
validation has been present since `ahci_init_one()` existed; the
vulnerability is long-standing, not a recent regression.
### Step 3.2: Fixes: tag
**Record:** N/A — no `Fixes:` tag.
### Step 3.3: Related file history
**Record:**
- Related but distinct: `62ced8e065787` — “Do not read the per port area
for unimplemented ports” (PI-register compliance; does not address
bogus `CAP.NP` vs BAR size).
- No other “BAR too small” fix in this tree.
- Patch series: v2 → v5 (Apr 25–28, 2026); committed version is v5.
### Step 3.4: Author context
**Record:** liyouhong is the reporter/fix author. Niklas Cassel
(AHCI/libata maintainer) applied the patch. Damien Le Moal (libata
maintainer) reviewed it.
### Step 3.5: Dependencies
**Record:** **Standalone.** Uses `ahci_nr_ports()` (inline in `ahci.h`
since `365cfa1ed5a36`), `readl()`, `pci_resource_len()`, `HOST_CAP` —
all present in 6.18.44. No series prerequisites.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original discussion
**Record:**
- **b4 dig -c c4086c6:**
https://patch.msgid.link/20260428020935.2049617-1-dayou5941@163.com
- **b4 dig -a:** v2 (Apr 25), v3/v4 (Apr 27), v5 (Apr 28, 2026) —
committed version is latest
- **Key feedback:** Niklas Cassel applied to libata `for-7.2`, corrected
commit-log wording about `CAP.NP` range (1–32 is valid per spec; the
issue is BAR mismatch, not “impossible” port count). No NAKs.
### Step 4.2: Reviewers
**Record:** **b4 dig -w** CC’d: `linux-ide@vger.kernel.org`,
`dlemoal@kernel.org`, `cassel@kernel.org`, `liyouhong@kylinos.cn`.
Appropriate maintainers were involved.
### Step 4.3: Bug report
**Record:** Reported-by from Kylin OS. Commit Closes original report at
lore `20260422080322`. Panic mechanism described in patch and maintainer
reply. No stack trace in the retrieved mbox thread, but the OOB MMIO
path is verifiable in code.
### Step 4.4: Series context
**Record:** Standalone 1/1 patch. Five revision rounds addressed review
feedback; no companion patches required.
### Step 4.5: Stable list history
**Record:** No `Cc: stable` nomination found in the retrieved thread.
Absence is not a negative signal per review instructions.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `ahci_validate_bar_size()` (new), `ahci_init_one()`,
`ahci_nr_ports()`, `ahci_pci_save_initial_config()` →
`ahci_save_initial_config()`, `__ahci_port_base()`.
### Step 5.2: Callers
**Record:** `ahci_init_one()` is the `.probe` handler for
`ahci_pci_driver` (line 673), registered via `module_pci_driver()`.
Called during PCI device enumeration at boot or module load.
### Step 5.3: Callees
**Record:** `readl(hpriv->mmio + HOST_CAP)` (offset 0, always within
BAR), `ahci_nr_ports()`, `pci_resource_len()`.
### Step 5.4: Reachability
**Record:** **Userspace-triggerable indirectly** via PCI hotplug/module
load, but primary scenario is **boot** when the AHCI controller is
present in PCI space but disabled/misconfigured in BIOS. Any system with
`CONFIG_SATA_AHCI` and such hardware is affected.
### Step 5.5: Similar patterns
**Record:** `__ahci_port_base()` at `mmio + 0x100 + port_no * 0x80` is
the canonical layout used throughout AHCI. The validation formula
matches this exactly. No duplicate fix elsewhere in `drivers/ata/`.
---
## PHASE 6: CROSS-REFERENCE AGAINST LOCAL TREE (6.18.44)
### Step 6.1: Buggy code present?
**Record:** **YES.** Current `ahci_init_one()` maps MMIO at line 1987
and proceeds directly to `ahci_remap_check()` /
`ahci_pci_save_initial_config()` with no BAR-size check.
`ahci_validate_bar_size()` is **absent**. Upstream commit `c4086c6` is
**not** an ancestor of HEAD (`merge-base --is-ancestor` exit 1).
### Step 6.2: Backport complications
**Record:** **Clean apply.** `git format-patch -1 c4086c6 --stdout | git
apply --check` succeeded on HEAD. Line context around `pcim_iomap()`
matches the patch.
### Step 6.3: Related fixes already present?
**Record:** `62ced8e065787` (skip unimplemented ports in
`ahci_mark_external_port`) is present but does not address this
BAR/CAP.NP mismatch. No duplicate BAR validation found.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem criticality
**Record:** **drivers/ata/ahci** — IMPORTANT. AHCI is the standard SATA
driver on most x86/ARM desktops, laptops, and servers.
### Step 7.2: Activity
**Record:** Actively maintained in 6.18.y (recent commits: LPM quirks,
JMicron DMA, unimplemented-port fix). The underlying probe path is
mature; this bug has existed without validation for years.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who is affected
**Record:** Systems with an AHCI PCI device present but disabled or
misconfigured in BIOS (bogus `HOST_CAP`). Common on dual-controller or
unused-SATA configurations. Affects anyone building `CONFIG_SATA_AHCI`
(default on most distros).
### Step 8.2: Trigger conditions
**Record:** Boot or `modprobe ahci` when PCI enumerates a disabled AHCI
controller reporting `HOST_CAP = 0xFFFFFFFF` (or any `CAP.NP` value
whose port space exceeds BAR size). Not a race; deterministic on
affected hardware.
### Step 8.3: Failure mode severity
**Record:** **Kernel panic** from OOB MMIO access → **CRITICAL** (boot
failure, no graceful recovery).
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** HIGH — prevents boot-time panic on real hardware; clear
`-ENODEV` + warning instead.
- **Risk:** VERY LOW — 22-line defensive check, reviewed by maintainer,
applies cleanly.
- **Ratio:** Strongly favors backport.
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Fixes real kernel panic on probe (user-reported, Kylin OS)
- Reviewed by libata maintainer; applied by AHCI maintainer
- Small, self-contained, no dependencies
- Buggy code exists in 6.18.44; fix not yet present
- Applies cleanly
- Fails probe gracefully (`-ENODEV`) instead of panicking
**AGAINST backport:**
- None significant. Disabled-controller scenario is somewhat niche, but
panic severity outweighs rarity.
**Unresolved:**
- Full stack trace from original bug report not retrieved (lore Anubis
blocked direct fetch; mbox thread contained patch discussion, not the
original oops log). Panic mechanism is confirmed by code path
analysis.
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — simple arithmetic;
maintainer-reviewed; v5 after four revision rounds.
2. Fixes a real bug affecting users? **PASS** — Reported-by from
production distro user.
3. Important issue? **PASS** — kernel panic (CRITICAL).
4. Small and contained? **PASS** — 22 lines, one file.
5. No new features or APIs? **PASS** — probe-time validation only.
6. Can apply to local tree? **PASS** — `git apply --check` clean on
6.18.44.
### Step 9.3: Exception categories
**Record:** N/A (not a device ID, quirk, DT, build, or docs fix).
Qualifies on crash-fix merits alone.
### Step 9.4: Decision rationale
For Linux **6.18.44**, systems with a BIOS-disabled AHCI controller can
hit OOB MMIO during `ahci_init_one()` probe and panic the kernel. The
fix adds an early, spec-aligned BAR size check and fails probe safely.
It is small, maintainer-reviewed, standalone, and applies cleanly to
this tree. This is appropriate stable material.
---
## Verification
- **[Phase 1]** Parsed subject, tags, body; identified panic-on-probe
bug with BIOS-disabled AHCI scenario.
- **[Phase 2]** Diff: +22 lines in `drivers/ata/ahci.c`; new
`ahci_validate_bar_size()`, call in `ahci_init_one()`; OOB MMIO bug
class.
- **[Phase 3]** `git blame -L 1987,1992 drivers/ata/ahci.c`: iomap area
from `bdcddd0cdc39d` (2024); no `Fixes:` tag; related commit
`62ced8e065787` is distinct; `ahci_nr_ports()` present since
`365cfa1ed5a36`.
- **[Phase 3]** `git merge-base --is-ancestor c4086c6 HEAD` → exit 1
(fix **not** in 6.18.44).
- **[Phase 4]** `b4 dig -c c4086c6`: lore URL found; `b4 dig -a`: v2–v5
series; `b4 dig -w`: maintainers CC’d; mbox: Damien Le Moal Reviewed-
by, Niklas applied, no NAKs, no stable Cc.
- **[Phase 5]** `ahci_init_one` is `.probe` for `ahci_pci_driver` (line
673); panic path via `ahci_save_initial_config()` `readl(port_mmio +
PORT_CMD)` at `libahci.c:590-592` and `__ahci_port_base()` at
`ahci.h:453-458`.
- **[Phase 6]** `git describe HEAD` → v6.18.44; `make kernelversion`
equivalent → 6.18.44; `ahci_validate_bar_size` absent; `git apply
--check` clean.
- **[Phase 8]** Failure mode: OOB MMIO → kernel panic; severity
CRITICAL; trigger: BIOS-disabled AHCI with bogus `HOST_CAP`.
**YES****Verdict: YES** — backport to this tree (Linux 6.18.44).
The patch adds a small check in `ahci_init_one()` so probe fails with
`-ENODEV` when `HOST_CAP.NP` claims more ports than the BAR can hold.
That avoids out-of-bounds MMIO access and a kernel panic when an AHCI
controller is disabled in BIOS but still shows up on PCI with bogus
registers (e.g. `HOST_CAP = 0xFFFFFFFF`).
It’s a 22-line, single-file fix, maintainer-reviewed, applies cleanly to
6.18.44, and the bug is still present there.
drivers/ata/ahci.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 1d73a53370cf3..b4e5d347151a9 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1888,6 +1888,24 @@ static ssize_t remapped_nvme_show(struct device *dev,
static DEVICE_ATTR_RO(remapped_nvme);
+static int ahci_validate_bar_size(struct pci_dev *pdev, int bar,
+ struct ahci_host_priv *hpriv)
+{
+ u32 cap = readl(hpriv->mmio + HOST_CAP);
+ unsigned int max_ports = ahci_nr_ports(cap);
+ u32 last_port_end = 0x100 + (max_ports * 0x80);
+ resource_size_t bar_size = pci_resource_len(pdev, bar);
+
+ if (last_port_end > bar_size) {
+ dev_warn(&pdev->dev,
+ "BAR%d too small for %u ports (last port ends at %#x, BAR %pa)\n",
+ bar, max_ports, last_port_end, &bar_size);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
unsigned int board_id = ent->driver_data;
@@ -1988,6 +2006,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!hpriv->mmio)
return -ENOMEM;
+ rc = ahci_validate_bar_size(pdev, ahci_pci_bar, hpriv);
+ if (rc)
+ return rc;
+
/* detect remapped nvme devices */
ahci_remap_check(pdev, ahci_pci_bar, hpriv);
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] ata: libata-core: Disable LPM on some WD drives
[not found] <20260831133314.4125787-1-sashal@kernel.org>
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-5.10] ata: ahci: fail probe if BAR too small for claimed ports Sasha Levin
@ 2026-08-31 13:23 ` Sasha Levin
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-6.12] ata: libata-core: Disable LPM on WD Green 2.5 480GB Sasha Levin
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-08-31 13:23 UTC (permalink / raw)
To: patches, stable
Cc: Niklas Cassel, Damien Le Moal, Sasha Levin, linux-ide,
linux-kernel
From: Niklas Cassel <cassel@kernel.org>
[ Upstream commit 356d8241cf3c7b07a4a491dbab43b5a41513ca86 ]
According to a user report WDC WD100EFGX-68CPLN0 and WDC WD102KFBX-68M95N0
have problems with LPM.
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220693
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## Phase 1: Commit Message Forensics
**Step 1.1 — Subject line**
- Record: `[ata: libata-core]` `[Disable]` — Add ATA device quirks to
disable Link Power Management (LPM) on two specific Western Digital
drive models.
**Step 1.2 — Tags**
- Record:
- `Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220693`
- `Signed-off-by: Niklas Cassel <cassel@kernel.org>` (author/subsystem
maintainer)
- `Signed-off-by: Damien Le Moal <dlemoal@kernel.org>` (libata
maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, or `Cc:
stable@vger.kernel.org` tags
- Notable: bugzilla closure link; maintainer sign-offs from libata
maintainers
**Step 1.3 — Body analysis**
- Record:
- **Bug:** WDC WD100EFGX-68CPLN0 and WDC WD102KFBX-68M95N0 have
problems with LPM
- **Symptom (from bugzilla):** "SATA bus goes offline after a while"
(bug 220693, reported 2025-10-22)
- **Version info:** None in commit message
- **Root cause (from patch comment):** Existing
`ATA_QUIRK_WD_BROKEN_LPM` only applies to SATA Gen1 drives; these
modern WD models need unconditional `ATA_QUIRK_NOLPM`
**Step 1.4 — Hidden bug fix detection**
- Record: Not disguised — this is an explicit hardware quirk/workaround
fix, though the subject says "Disable" rather than "fix". Classic
device-specific LPM workaround pattern.
---
## Phase 2: Diff Analysis
**Step 2.1 — Change inventory**
- Record:
- Files: `drivers/ata/libata-core.c` (+8 lines, 0 removed)
- Functions: modifies `__ata_dev_quirks[]` static table only
- Scope: single-file, surgical quirk-table addition
**Step 2.2 — Code flow change**
- Record:
- **Hunk (quirk table):** Before — no quirk entries for WD100EFGX or
WD102KFBX; LPM enabled normally. After — both models matched via
`glob_match()` and assigned `ATA_QUIRK_NOLPM`, which forces
`ATA_LPM_MAX_POWER` in `ata_dev_config_lpm()` and prevents LPM in
`ata_scsi_lpm_supported()`.
**Step 2.3 — Bug mechanism**
- Record:
- **Category:** Hardware workaround (LPM incompatibility)
- **Mechanism:** These WD drives malfunction when SATA link power
management is used (slumber/partial states). Without the quirk,
`ata_dev_config_lpm()` does not disable LPM. With `ATA_QUIRK_NOLPM`,
LPM is disabled at probe and the port policy is forced to max power,
preventing the drive from dropping off the SATA bus.
**Step 2.4 — Fix quality**
- Record:
- Obviously correct: uses established `ATA_QUIRK_NOLPM` mechanism
already used for ADATA, Seagate, Samsung, and other drives in the
same table
- Minimal and surgical: two model strings plus explanatory comment
- Regression risk: very low; only affects exact model matches; trade-
off is slightly higher power consumption on those drives (standard
accepted cost of NOLPM quirks)
---
## Phase 3: Git History Investigation
**Step 3.1 — Blame**
- Record: WD `ATA_QUIRK_WD_BROKEN_LPM` entries date to commit
`ecd75ad514d73` ("libata: disable LPM for some WD SATA-I devices"),
present since v4.6 era. The buggy behavior (no quirk for these models)
is simply the absence of entries — not a recently introduced
regression in libata code.
**Step 3.2 — Fixes: tag**
- Record: N/A — no `Fixes:` tag present.
**Step 3.3 — File history**
- Record: Recent stable-tree libata LPM quirk backports include:
- `2229b4cf97301` — ADATA SU680 NOLPM (backported to 6.18.y)
- `87f0349beaaca` — ST1000DM010 NOLPM
- `a70fd483c4b93` — ST2000DM008 NOLPM
- Standalone fix; part of a 2-patch series on mainline (patch 2 adds a
different WD Green model) but patch 1 is self-contained.
**Step 3.4 — Author context**
- Record: Niklas Cassel is libata maintainer; Damien Le Moal is primary
libata maintainer. Both signed off. Maintainer applied series to
`for-7.2-fixes` per lore reply.
**Step 3.5 — Dependencies**
- Record: No dependencies. `ATA_QUIRK_NOLPM`, `ata_dev_quirks()`,
`ata_dev_config_lpm()`, and `glob_match()` all exist in this tree.
Applies cleanly (`git apply --check` passed).
---
## Phase 4: Mailing List and External Research
**Step 4.1 — Original discussion**
- Record:
- Lore URL:
https://patch.msgid.link/20260728111310.722450-5-cassel@kernel.org
- Series: v1 only (no further revisions)
- Damien Le Moal: "Applied to for-7.2-fixes. Thanks!"
- No NAKs; no explicit stable nomination in thread
**Step 4.2 — Reviewers**
- Record: CC'd to `linux-ide@vger.kernel.org`, Damien Le Moal, Ronald
Garcia Vazquez (likely reporter contact). Maintainers directly
involved.
**Step 4.3 — Bug report**
- Record:
- Bugzilla 220693: "SATA bus goes offline after a while"
- Reported by Emerson Pinter, 2025-10-22
- Marked as regression with bisect to `459779d04ae8` (block read-ahead
change) — that commit is **not** in the 6.18.y tree; the LPM quirk
fix addresses the drive-specific failure mode regardless
- Severity: disk/bus disappearance is a serious usability and
potential data-integrity issue
**Step 4.4 — Related patches**
- Record: Patch 2/2 (`WD Green 2.5 480GB`) is a separate one-line quirk
for a different model; not required for this commit to function.
**Step 4.5 — Stable list**
- Record: No stable-list discussion found for this specific commit.
Precedent: ADATA SU680 NOLPM quirk (`2229b4cf97301`) was explicitly
nominated with `Cc: stable@vger.kernel.org` and backported to 6.18.y.
---
## Phase 5: Code Semantic Analysis
**Step 5.1 — Key functions**
- Record: `__ata_dev_quirks[]` (modified), `ata_dev_quirks()`
(consumer), `ata_dev_config_lpm()` (applies NOLPM),
`ata_scsi_lpm_supported()` (checks NOLPM)
**Step 5.2 — Callers**
- Record: `ata_dev_quirks()` called from device identification path at
line 2978 (`dev->quirks |= ata_dev_quirks(dev)`), during normal SATA
device probe/enumeration — common boot and hotplug path.
**Step 5.3 — Callees**
- Record: `glob_match()` for model string matching; quirk bits consumed
by `ata_dev_config_lpm()` and `ata_scsi_lpm_supported()`.
**Step 5.4 — Reachability**
- Record: Triggered automatically when a matching WD drive is detected
on any SATA controller using libata. No special config needed beyond
`CONFIG_ATA`.
**Step 5.5 — Similar patterns**
- Record: Extensive existing NOLPM quirk entries in the same table
(ADATA SU680, ST1000DM010, ST2000DM008, Samsung SSDs, etc.) —
identical fix pattern.
---
## Phase 6: Cross-Reference Against Local Tree
**Step 6.1 — Buggy code in tree**
- Record: Local tree is **Linux 6.18.44** (`v6.18.44-2-g1b9e1abadee04`,
detached from `stable/linux-6.18.y`). The WD100EFGX/WD102KFBX quirk
entries are **absent**; commit `356d8241cf3c7` is on `master` only
(`NOT_IN_CURRENT_TREE`). The quirk infrastructure and
`ATA_QUIRK_NOLPM` are fully present. Bug affects any user with these
drive models on 6.18.y.
**Step 6.2 — Backport complications**
- Record: Clean apply confirmed. Line numbers differ slightly (stable
table ends at line 4373 vs mainline 4413) but patch applies without
conflict.
**Step 6.3 — Related fixes already present**
- Record: Similar NOLPM quirks for ADATA SU680, ST1000DM010, ST2000DM008
already in 6.18.y. No duplicate fix for these WD models.
---
## Phase 7: Subsystem and Maintainer Context
**Step 7.1 — Subsystem criticality**
- Record: `drivers/ata/` — IMPORTANT (storage stack; affects users with
affected hardware)
**Step 7.2 — Subsystem activity**
- Record: Actively maintained in 6.18.y with recent stable backports
including LPM quirks, error handling fixes, and SCSI path fixes.
---
## Phase 8: Impact and Risk Assessment
**Step 8.1 — Who is affected**
- Record: Users with WDC WD100EFGX-68CPLN0 or WDC WD102KFBX-68M95N0
drives on any libata SATA port. WD Red/Black enterprise/consumer HDDs
— real, commonly deployed hardware.
**Step 8.2 — Trigger conditions**
- Record: Occurs during normal operation when LPM is active on the SATA
link — not exotic. Triggered on every boot/probe for matching drives;
failure manifests over time ("after a while").
**Step 8.3 — Failure mode severity**
- Record: SATA bus goes offline → drive disappears, I/O errors,
potential data loss. Severity: **HIGH** (serious functional failure,
possible data integrity impact).
**Step 8.4 — Risk-benefit**
- Record:
- Benefit: **High** for affected hardware — restores reliable disk
operation
- Risk: **Very low** — 8-line quirk addition, exact model match only,
established mechanism
- Ratio: strongly favors backport
---
## Phase 9: Final Synthesis
**Step 9.1 — Evidence summary**
FOR backporting:
- Fixes real user-reported bug (bugzilla 220693)
- Hardware quirk — explicit stable exception category
- Identical pattern to NOLPM quirks already backported to 6.18.y
- Small, surgical, applies cleanly
- Subsystem maintainer authored and applied
- Serious failure mode (SATA bus offline)
AGAINST backporting:
- No `Tested-by:` on this specific commit (minor; ADATA quirk had one)
- No explicit `Cc: stable` tag (not a negative signal per instructions)
- Bugzilla regression bisect points elsewhere, but fix targets
documented LPM failure mode
**Step 9.2 — Stable rules checklist**
1. Obviously correct and tested? **PASS** — standard quirk mechanism;
maintainer-reviewed
2. Fixes a real bug affecting users? **PASS** — bugzilla user report,
SATA bus offline
3. Important issue? **PASS** — drive/bus failure, HIGH severity
4. Small and contained? **PASS** — 8 lines, one file
5. No new features or APIs? **PASS** — quirk table entries only
6. Can apply to local tree? **PASS** — clean apply verified
**Step 9.3 — Exception category**
- Record: **Hardware quirk/workaround** — automatic stable
qualification.
**Step 9.4 — Decision rationale**
This commit adds two model-specific `ATA_QUIRK_NOLPM` entries for WD
drives that drop off the SATA bus when LPM is enabled. The fix uses
infrastructure already present and proven in 6.18.y through prior NOLPM
backports. It is not in the current 6.18.44 tree but applies cleanly and
addresses a serious, user-visible hardware failure. This is textbook
stable material.
---
## Verification
- [Phase 1] Parsed commit `356d8241cf3c7`: subject, tags, body, bugzilla
link
- [Phase 2] Full diff reviewed: 8 lines added to `__ata_dev_quirks[]` in
`drivers/ata/libata-core.c`
- [Phase 3] `git describe HEAD`: v6.18.44 (6.18.y stable tree)
- [Phase 3] `git merge-base --is-ancestor 356d8241cf3c7 HEAD`:
NOT_IN_CURRENT_TREE
- [Phase 3] `git blame` on WD_BROKEN_LPM lines: introduced in
`ecd75ad514d73` (v4.6 era)
- [Phase 3] Prior NOLPM backports in stable: `2229b4cf97301`,
`87f0349beaaca`, `a70fd483c4b93` confirmed
- [Phase 4] `b4 dig -c 356d8241cf3c7`: lore thread found
- [Phase 4] `b4 dig -a`: v1 only, no later revisions
- [Phase 4] `b4 dig -w`: CC to linux-ide, Damien Le Moal, reporter
- [Phase 4] Mbox: Damien Le Moal applied to for-7.2-fixes; patch 2/2 is
separate drive
- [Phase 4] Bugzilla 220693: "SATA bus goes offline after a while",
reported 2025-10-22
- [Phase 5] `grep ata_dev_quirks`: called from device probe at line 2978
- [Phase 5] Read `ata_dev_config_lpm()`: NOLPM forces
`ATA_LPM_MAX_POWER`
- [Phase 5] Read `ata_scsi_lpm_supported()`: checks `ATA_QUIRK_NOLPM`
- [Phase 6] `grep WD100EFGX|WD102KFBX` in tree: no matches (bug present)
- [Phase 6] `git format-patch | git apply --check`: applies cleanly
- [Phase 6] `ATA_QUIRK_NOLPM` defined in `include/linux/libata.h`:
present
- [Phase 8] Bugzilla regression bisect commit `459779d04ae8`: NOT in
6.18.y tree (irrelevant to applicability)
**YES**The background checks finished and match the earlier analysis:
- **Master search:** Found commit `356d8241cf3c7` — "ata: libata-core:
Disable LPM on some WD drives"
- **Tree check:** That commit is on `master` only, **not** in the
current 6.18.44 stable checkout
The backport recommendation stands: **YES** — add the two WD
`ATA_QUIRK_NOLPM` entries for WD100EFGX and WD102KFBX; the patch applies
cleanly to this tree.
drivers/ata/libata-core.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index f0753f5e57a8e..ae1e5f82026c5 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4372,6 +4372,14 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = {
{ "WDC WD3000JD-*", NULL, ATA_QUIRK_WD_BROKEN_LPM },
{ "WDC WD3200JD-*", NULL, ATA_QUIRK_WD_BROKEN_LPM },
+ /*
+ * WD drives with LPM issues (irrespective of supported SATA speeds).
+ * (Unlike ATA_QUIRK_WD_BROKEN_LPM, which is only applied if the drive
+ * exposes SATA Gen1 speed support, and SATA Gen1 speed support only.)
+ */
+ { "WDC WD100EFGX-68CPLN0", NULL, ATA_QUIRK_NOLPM },
+ { "WDC WD102KFBX-68M95N0", NULL, ATA_QUIRK_NOLPM },
+
/*
* This sata dom device goes on a walkabout when the ATA_LOG_DIRECTORY
* log page is accessed. Ensure we never ask for this log page with
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] ata: libata-core: Disable LPM on WD Green 2.5 480GB
[not found] <20260831133314.4125787-1-sashal@kernel.org>
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-5.10] ata: ahci: fail probe if BAR too small for claimed ports Sasha Levin
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.12] ata: libata-core: Disable LPM on some WD drives Sasha Levin
@ 2026-08-31 13:24 ` Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.12] ata: libata-core: Disable LPM on WDC WD141KFGX-68FH9N0 Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-5.10] ata: libata-pmp: add JMicron JMS562 quirk Sasha Levin
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-08-31 13:24 UTC (permalink / raw)
To: patches, stable
Cc: Niklas Cassel, Damien Le Moal, Sasha Levin, linux-ide,
linux-kernel
From: Niklas Cassel <cassel@kernel.org>
[ Upstream commit d549df8a0ace611bff0a336a907f93420648b462 ]
According to a user report, the WD Green 2.5 480GB has problems with LPM.
Link: https://lore.kernel.org/linux-ide/CAGiKK17Fg4SgS+y0GzD3new44QzD_yPZU5V3ZeHdUr9mFnfn1Q@mail.gmail.com/
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
# Stable Backport Analysis: `ata: libata-core: Disable LPM on WD Green
2.5 480GB`
**Local tree:** Linux **6.18.44** (`v6.18.44-2-g1b9e1abadee04`)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[ata: libata-core]` `[Disable]` — disable Link Power
Management (LPM) for the WD Green 2.5 480GB SSD via a device quirk.
### Step 1.2: Tags
**Record:**
- **Link:** `https://lore.kernel.org/linux-ide/CAGiKK17Fg4SgS+y0GzD3new4
4QzD_yPZU5V3ZeHdUr9mFnfn1Q@mail.gmail.com/` (user report)
- **Signed-off-by:** Niklas Cassel `<cassel@kernel.org>` (libata
maintainer)
- **Signed-off-by:** Damien Le Moal `<dlemoal@kernel.org>` (libata co-
maintainer)
- No `Fixes:`, `Reported-by:`, `Cc: stable`, `Tested-by:`, or `Reviewed-
by:` in the candidate message
- Part of a 2-patch series: `[PATCH 0/2] ata: disable LPM on some WDC
drives` (2026-07-28)
### Step 1.3: Body analysis
**Record:**
- **Bug:** WD Green 2.5 480GB has problems with SATA Link Power
Management.
- **Symptom:** Per Phoronix coverage of the merged upstream series, the
drive typically **disappears 2–3 minutes after boot** and stays
offline until reboot.
- **Root cause:** Drive firmware does not tolerate LPM; kernel enables
LPM by default unless quirked.
- **Workaround:** `libata.force=nolpm` boot parameter (confirmed by
Phoronix).
### Step 1.4: Hidden bug fix?
**Record:** Yes — presented as a quirk addition, but it fixes a real
hardware compatibility bug (drive drop-off), not cosmetic cleanup.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- **Files:** `drivers/ata/libata-core.c` (+1 line)
- **Function/area:** `__ata_dev_quirks[]` static quirk table
- **Scope:** Single-line, single-file hardware quirk
### Step 2.2: Code flow change
**Record:**
- **Before:** WD Green 2.5 480GB not in quirk table → LPM may be enabled
→ drive can drop off link.
- **After:** Model matches quirk → `ATA_QUIRK_NOLPM` set during
`ata_dev_configure()` → `ata_dev_config_lpm()` forces
`ATA_LPM_MAX_POWER` and logs `"LPM support broken, forcing
max_power"`.
- **Path:** Device probe/enumeration (normal boot path for affected
hardware).
### Step 2.3: Bug mechanism
**Record:**
- **Category:** Hardware workaround / quirk
- **Mechanism:** Broken device firmware mishandles SATA LPM; kernel
disables LPM for this exact model string, same pattern as existing
Seagate, ADATA, Samsung, Crucial NOLPM entries in this tree.
### Step 2.4: Fix quality
**Record:**
- Obviously correct: identical to multiple existing NOLPM quirk entries
already in 6.18.44.
- Minimal scope: one table entry.
- **Regression risk:** Very low — only affects drives whose ATA identify
model string exactly matches `"WD Green 2.5 480GB"` (per
`glob_match()` full-string semantics in `lib/glob.c`).
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:** Quirk table in this tree dates to long-standing libata code
(WD SATA-I `ATA_QUIRK_WD_BROKEN_LPM` entries unchanged since v6.18 merge
base). The missing WD Green entry is an omission, not a recently
introduced regression in kernel code.
### Step 3.2: Fixes: tag
**Record:** N/A — no `Fixes:` tag.
### Step 3.3: Related file history
**Record:** Recent NOLPM quirk backports already in **this** 6.18.44
tree:
- `a70fd483c4b93` — ST2000DM008-2FR102 (Jan 2026)
- `87f0349beaaca` — ST1000DM010-2EP102 (Mar 2026, `Cc: stable`)
- `2229b4cf97301` — ADATA SU680 (Mar 2026, `Cc: stable`)
This commit is patch **2/2** of a series; patch **1/2**
(`20b72163992eb`, WD100EFGX/WD102KFBX) is **not** in current HEAD but is
independent for this drive.
### Step 3.4: Author context
**Record:** Niklas Cassel is libata maintainer; Damien Le Moal is co-
maintainer. Same authors/maintainers as prior NOLPM quirk backports in
this tree.
### Step 3.5: Dependencies
**Record:**
- Upstream patch 2/2 context places the line after WD100EFGX/WD102KFBX
entries from patch 1/2.
- In **6.18.44**, those WD Red Plus entries do not exist; the quirk can
be added to the existing NOLPM block (lines 4192–4197, alongside
ADATA/Seagate entries).
- **Standalone for this device:** does not require patch 1/2 to
function.
- Stable backport commit `f6fe42e574cf6` exists in the repo but is
**not** an ancestor of HEAD (`git merge-base --is-ancestor` exit 1).
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original discussion
**Record:**
- `b4 dig -c d549df8a0ace6` →
`https://patch.msgid.link/20260728111310.722450-6-cassel@kernel.org`
- Ratatoskr archive confirms series: PATCH 0/2, 1/2, 2/2 (2026-07-28);
Damien Le Moal replied 2026-07-29 (series accepted upstream).
- Direct lore fetch blocked (403/Anubis); user report URL not directly
readable.
### Step 4.2: Reviewers
**Record:** `b4 dig -w` returned only the msgid link (no recipient
list). Upstream SOBs from Niklas Cassel and Damien Le Moal confirm
maintainer acceptance.
### Step 4.3: Bug report details
**Record:**
- **Phoronix (2026-08-01):** WD Green 2.5 480GB disappears 2–3 minutes
after boot; `libata.force=nolpm` is the workaround.
- **linux-hardware.org:** 114 probe entries for this device, many marked
**malfunc** across diverse systems (Dell, Lenovo, HP, Intel NUC,
etc.).
- **bugzilla.kernel.org #220693** referenced by patch 1/2 (WD Red
drives), not this specific drive.
### Step 4.4: Series context
**Record:** Patch 1/2 adds WD100EFGX/WD102KFBX NOLPM entries; patch 2/2
adds WD Green. Each is independently useful for its respective hardware.
### Step 4.5: Stable list history
**Record:** Not searched on lore stable list (blocked). Prior NOLPM
quirk commits in this tree explicitly carried `Cc:
stable@vger.kernel.org`.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `__ata_dev_quirks[]`, `ata_dev_quirks()`,
`ata_dev_configure()`, `ata_dev_config_lpm()`.
### Step 5.2: Callers
**Record:** `ata_dev_quirks()` called from `ata_dev_configure()` (line
2978); `ata_dev_config_lpm()` called during ATA device configuration
(lines 3096, 3172). Every SATA disk probe goes through this path.
### Step 5.3: Callees
**Record:** `glob_match()` for model matching; `ata_dev_warn()` when
forcing max power; `ata_dev_set_feature()` for DIPM disable if needed.
### Step 5.4: Reachability
**Record:** Triggered automatically at boot when the physical drive is
present and LPM policy is not already max power. No special config
required beyond normal SATA/AHCI.
### Step 5.5: Similar patterns
**Record:** At least 20+ `ATA_QUIRK_NOLPM` entries already in `libata-
core.c` in this tree, including three backported in 2026 for Seagate and
ADATA drives with identical failure modes.
---
## PHASE 6: CROSS-REFERENCING AGAINST LOCAL TREE (6.18.44)
### Step 6.1: Does buggy code exist?
**Record:** **Yes.** `ATA_QUIRK_NOLPM`, `ata_dev_config_lpm()`, and the
quirk table all exist. The WD Green entry is **absent** (`grep` finds no
match). LPM can still be enabled for this drive in 6.18.44.
### Step 6.2: Backport complications
**Record:** **Minor placement adjustment.** Upstream context assumes
patch 1/2 entries exist; in 6.18.44 the line belongs in the existing
NOLPM section (~line 4197). Trivial one-line addition, no structural
changes needed.
### Step 6.3: Related fixes already present?
**Record:** No WD Green quirk in HEAD. Similar NOLPM quirk pattern
already established by ST/ADATA backports.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem criticality
**Record:** `drivers/ata/` — **IMPORTANT** (storage stack; affects any
system with this SATA SSD).
### Step 7.2: Subsystem activity
**Record:** Actively maintained; multiple ATA quirk/fix commits in
6.18.44 history.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who is affected
**Record:** Users with a WD Green 2.5 480GB SATA SSD — a widely deployed
consumer SSD (114+ hardware probes documented).
### Step 8.2: Trigger conditions
**Record:** Normal boot with LPM enabled (default on many controllers).
Reproducible within minutes per user/Phoronix reports. Unprivileged
users cannot trigger the kernel bug directly, but all users of this
hardware are affected at boot.
### Step 8.3: Failure mode severity
**Record:** Drive **disappears from the SATA bus** until reboot —
**HIGH** severity. Can cause I/O errors, filesystem errors, and
effective data unavailability on affected drives (potential corruption
if mounted read-write).
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** HIGH — restores reliable operation for a known-broken
device model.
- **Risk:** VERY LOW — one-line quirk, no API changes, no behavior
change for other drives.
- **Ratio:** Strongly favors backport.
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Real user-reported hardware bug with documented symptoms (drive drop-
off).
- Same fix class as three NOLPM quirk backports already in 6.18.44.
- Maintainers (Cassel, Le Moal) authored and accepted upstream.
- Trivial, obviously correct one-line change.
- Falls under stable **hardware quirk exception**.
- Infrastructure (`ATA_QUIRK_NOLPM`, quirk table, LPM config) fully
present in 6.18.44.
- Workaround (`libata.force=nolpm`) confirms the diagnosis.
**AGAINST backport:**
- Patch 2/2 upstream context references patch 1/2 placement (cosmetic
backport adjustment only).
- No `Tested-by:` or explicit `Cc: stable` on this specific commit (not
disqualifying).
- Exact ATA identify string not independently verified here (maintainer-
derived; low risk).
### Step 9.2: Stable rules checklist
| Criterion | Result |
|-----------|--------|
| 1. Obviously correct and tested? | **PASS** — standard quirk; upstream
merged; maintainer SOBs |
| 2. Fixes a real bug affecting users? | **PASS** — drive disappears
with LPM enabled |
| 3. Important issue? | **PASS** — HIGH: storage device becomes
inaccessible |
| 4. Small and contained? | **PASS** — 1 line, 1 file |
| 5. No new features/APIs? | **PASS** — quirk table entry only |
| 6. Can apply to local tree? | **PASS** — add to existing NOLPM section
|
### Step 9.3: Exception category
**Record:** **Hardware quirk/workaround** — textbook stable material.
### Step 9.4: Decision rationale
For Linux **6.18.44**, this commit should be backported. The WD Green
2.5 480GB is a real, widely used drive that becomes unreliable when LPM
is enabled. The fix is a single `ATA_QUIRK_NOLPM` table entry — the same
approach already used in this tree for Seagate and ADATA drives with
identical LPM failure modes. The change is low risk, self-contained, and
does not depend on patch 1/2 of the upstream series.
---
## Verification
- **[Phase 1]** Parsed subject, tags, body; identified as patch 2/2 of
WDC LPM series.
- **[Phase 1]** Link tag points to linux-ide user report (direct fetch
blocked).
- **[Phase 2]** Diff: +1 line in `__ata_dev_quirks[]` with
`ATA_QUIRK_NOLPM`.
- **[Phase 2]** Read `ata_dev_config_lpm()` at lines 2876–2906: NOLPM
forces `ATA_LPM_MAX_POWER`.
- **[Phase 2]** Read `glob_match()` in `lib/glob.c`: pattern must match
entire string.
- **[Phase 3]** `git describe HEAD` → `v6.18.44-2-g1b9e1abadee04`;
Makefile VERSION 6.18.44.
- **[Phase 3]** `grep "WD Green"` in tree → no matches (quirk absent
from HEAD).
- **[Phase 3]** Found prior NOLPM backports: `a70fd483c4b93`,
`87f0349beaaca`, `2229b4cf97301`.
- **[Phase 3]** `git show f6fe42e574cf6` — stable-prepared backport
exists but not in HEAD.
- **[Phase 3]** `git merge-base --is-ancestor f6fe42e574cf6 HEAD` → exit
1 (not in HEAD).
- **[Phase 3]** `git show 20b72163992eb` — patch 1/2 also not in HEAD.
- **[Phase 4]** `b4 dig -c d549df8a0ace6` → patch msgid link found.
- **[Phase 4]** Ratatoskr archive: series structure and Damien Le Moal
reply confirmed.
- **[Phase 4]** Phoronix article: drive disappears 2–3 min after boot;
`libata.force=nolpm` workaround.
- **[Phase 4]** linux-hardware.org: 114 probes, many "malfunc" status
entries.
- **[Phase 5]** `ata_dev_quirks()` called from `ata_dev_configure()`
line 2978.
- **[Phase 5]** `ata_dev_config_lpm()` called at lines 3096, 3172.
- **[Phase 6]** `ATA_QUIRK_NOLPM` defined in `include/linux/libata.h`.
- **[Phase 6]** NOLPM quirk section present at lines 4192–4197 in
current tree.
- **[Phase 6]** Backport needs placement in existing NOLPM block, not
after absent WD100EFGX entries.
- **[Phase 8]** Failure mode: drive bus drop-off, severity HIGH.
**YES**The background check confirmed the stable backport commit exists
in the repo as `f6fe42e574cf6` ("Disable LPM on WD Green 2.5 480GB"),
but it is **not** on the current HEAD (`6.18.44`). The quirk is still
missing from the checked-out tree.
The earlier analysis stands: this is a one-line hardware quirk fix in
the same category as the Seagate/ADATA NOLPM backports already in
6.18.y, and it should be backported.
**YES**
drivers/ata/libata-core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index ae1e5f82026c5..a7a89b675a912 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4379,6 +4379,7 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = {
*/
{ "WDC WD100EFGX-68CPLN0", NULL, ATA_QUIRK_NOLPM },
{ "WDC WD102KFBX-68M95N0", NULL, ATA_QUIRK_NOLPM },
+ { "WD Green 2.5 480GB", NULL, ATA_QUIRK_NOLPM },
/*
* This sata dom device goes on a walkabout when the ATA_LOG_DIRECTORY
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] ata: libata-core: Disable LPM on WDC WD141KFGX-68FH9N0
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (2 preceding siblings ...)
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-6.12] ata: libata-core: Disable LPM on WD Green 2.5 480GB Sasha Levin
@ 2026-08-31 13:28 ` Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-5.10] ata: libata-pmp: add JMicron JMS562 quirk Sasha Levin
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-08-31 13:28 UTC (permalink / raw)
To: patches, stable
Cc: Niklas Cassel, Damien Le Moal, Sasha Levin, linux-ide,
linux-kernel
From: Niklas Cassel <cassel@kernel.org>
[ Upstream commit 3971921a055330669b281962ff723d1abb76a58c ]
According to a user report, WDC WD141KFGX-68FH9N0 has problems with LPM.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=220693
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The `git log -S "WD141KFGX"` search finished with no results on
`linux-6.18.y` — that model string has never appeared in this stable
branch. It only shows up on mainline in commit `3971921a05533`, which
supports the **YES** backport verdict.
drivers/ata/libata-core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index a7a89b675a912..ef7f93aca36d1 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4379,6 +4379,7 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = {
*/
{ "WDC WD100EFGX-68CPLN0", NULL, ATA_QUIRK_NOLPM },
{ "WDC WD102KFBX-68M95N0", NULL, ATA_QUIRK_NOLPM },
+ { "WDC WD141KFGX-68FH9N0", NULL, ATA_QUIRK_NOLPM },
{ "WD Green 2.5 480GB", NULL, ATA_QUIRK_NOLPM },
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] ata: libata-pmp: add JMicron JMS562 quirk
[not found] <20260831133314.4125787-1-sashal@kernel.org>
` (3 preceding siblings ...)
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.12] ata: libata-core: Disable LPM on WDC WD141KFGX-68FH9N0 Sasha Levin
@ 2026-08-31 13:28 ` Sasha Levin
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-08-31 13:28 UTC (permalink / raw)
To: patches, stable
Cc: Xu Rao, Damien Le Moal, Niklas Cassel, Sasha Levin, linux-ide,
linux-kernel
From: Xu Rao <raoxu@uniontech.com>
[ Upstream commit c62aff1174cf88e10716c7513702443c47551fc6 ]
JMicron JMS562, as used in QNAP QDA-A2AR RAID1 adapters, may
keep the exported ATA device not ready while the array is rebuilding.
In this state, libata may repeatedly try to softreset and classify
the fan-out link. On the affected adapter, this can time out, make
PMP/SCR access fail, and eventually disable the fan-out link before
the RAID volume is exported.
A failing boot shows the fan-out link failing SRST, PMP access
timing out, SCR read failing, and the link being disabled:
ata4.00: softreset failed (device not ready)
ata4.15: qc timeout after 3000 msecs (cmd 0xe4)
ata4.00: failed to read SCR 0 (Emask=0x4)
ata4.00: failed to recover link after 3 tries, disabling
After that, the root filesystem on the exported RAID volume cannot
be found.
Add JMS562 to the existing JMicron PMP quirk that disables LPM,
avoids softreset on fan-out links, and assumes an ATA device. This
prevents libata from dropping the exported RAID volume during rebuild
recovery.
Signed-off-by: Xu Rao <raoxu@uniontech.com>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## Phase 1: Commit Message Forensics
**Step 1.1 — Subject line**
- Record: `[ata: libata-pmp] [add] JMicron JMS562 quirk for QNAP
QDA-A2AR RAID adapter boot failure during array rebuild`
**Step 1.2 — Tags**
- Record:
- `Signed-off-by: Xu Rao <raoxu@uniontech.com>` (author)
- `Reviewed-by: Damien Le Moal <dlemoal@kernel.org>` (libata
maintainer)
- `Signed-off-by: Niklas Cassel <cassel@kernel.org>` (committer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Cc:
stable@vger.kernel.org`, or `Link:` tags
- Notable: maintainer review from Damien Le Moal; no syzbot/fuzzer
involvement
**Step 1.3 — Body analysis**
- Record:
- **Bug:** JMicron JMS562 PMP (QNAP QDA-A2AR RAID1 adapter) keeps
exported ATA device "not ready" during RAID rebuild
- **Symptom:** libata repeatedly softresets/classifies fan-out link →
PMP/SCR timeouts → link disabled → root filesystem on RAID volume
not found at boot
- **Failure log:** `softreset failed (device not ready)`, `qc
timeout`, `failed to read SCR 0`, `failed to recover link after 3
tries, disabling`
- **Root cause:** Missing quirk; libata error-handling path
incompatible with JMS562 behavior during rebuild
- **Fix approach:** Add device ID `0x0562` to existing JMicron quirk
block (disable LPM, avoid SRST, assume ATA)
- **Version info:** None stated in commit message
**Step 1.4 — Hidden bug fix detection**
- Record: Not hidden — this is an explicit hardware quirk fix. "Add
quirk" language is standard for ATA PMP workarounds; the commit
clearly describes a real boot failure.
---
## Phase 2: Diff Analysis
**Step 2.1 — Inventory**
- Record:
- Files: `drivers/ata/libata-pmp.c` (+6, -1)
- Function: `sata_pmp_quirks()`
- Scope: Single-file, surgical quirk addition (~7 lines net)
**Step 2.2 — Code flow change**
- Record:
- **Before:** JMicron vendor `0x197b` quirk applied only to device IDs
`0x2352` (JMB350) and `0x0325` (JMB394)
- **After:** Same quirk also applied to `0x0562` (JMS562)
- **Affected path:** PMP attach → `sata_pmp_quirks()` → per-link flags
set at initialization, before normal I/O
- **Flags set:** `ATA_LFLAG_NO_LPM | ATA_LFLAG_NO_SRST |
ATA_LFLAG_ASSUME_ATA` on all fan-out links
**Step 2.3 — Bug mechanism**
- Record:
- **Category:** Hardware workaround / logic correctness fix
- **Mechanism:** Without quirk, libata performs softreset (SRST) and
link classification on a device that legitimately reports "not
ready" during RAID rebuild. SRST/classify timeouts trigger error
recovery that disables the link before the RAID volume becomes
available. Quirk prevents SRST and assumes ATA class, matching
proven JMicron PMP behavior.
**Step 2.4 — Fix quality**
- Record:
- Obviously correct: extends an existing, proven quirk pattern for the
same vendor
- Minimal scope: one device ID + comment
- Low regression risk: only affects JMS562 PMP hardware; flags mirror
those already used for sibling JMicron chips
- No API, structure, or behavioral changes beyond this device
---
## Phase 3: Git History Investigation
**Step 3.1 — Blame**
- Record:
- JMicron quirk block introduced by `0afc6f5ba9541` (2011, Thermaltake
BlackX Duet / JMB350)
- JMB394 added by `efb9e0f4f4378` (2014) — that commit included `Cc:
stable@vger.kernel.org`
- Current tree has the quirk for `0x2352` and `0x0325` but not
`0x0562`
- Bug is not from a recent regression — it's a missing quirk for
hardware that was never covered
**Step 3.2 — Fixes: tag**
- Record: No `Fixes:` tag present; not applicable.
**Step 3.3 — Related file history**
- Record:
- Recent `libata-pmp.c` changes in this tree are unrelated (FBS/CBS
defer, tracepoints, spelling)
- Commit `c62aff1174cf8` is the only mainline change to this quirk
block since v6.18
- Standalone: v2 submission notes "sent as [PATCH 6/6], but this is a
standalone patch"
**Step 3.4 — Author context**
- Record: Xu Rao (UnionTech) — first ATA contribution in this tree.
Patch reviewed and committed by libata maintainers (Damien Le Moal,
Niklas Cassel).
**Step 3.5 — Dependencies**
- Record: No dependencies. `git apply --check` against current tree
succeeds. Quirk infrastructure and target `else if` block both exist
in v6.18.44.
---
## Phase 4: Mailing List and External Research
**Step 4.1 — Original discussion**
- Record:
- Lore URL: https://patch.msgid.link/71B4D0BBEC4F886F+20260610052835.1
111181-1-raoxu@uniontech.com
- Series: v1 as `[PATCH 6/6]`, v2 as standalone `[PATCH v2]`
(committed version)
- Damien Le Moal: "It is really unfortunate that JMicron keeps having
these issues. But I do not see any way around this" → `Reviewed-by:`
- No NAKs found
- No explicit stable nomination in thread
**Step 4.2 — Reviewers**
- Record: CC'd to `dlemoal@kernel.org`, `cassel@kernel.org`, `linux-
ide@vger.kernel.org`. Reviewed by libata maintainer Damien Le Moal.
**Step 4.3 — Bug report**
- Record: Real-world hardware bug on QNAP QDA-A2AR; concrete dmesg log
in commit message. No external bug tracker link. Severity for affected
users: cannot boot when root is on rebuilding RAID volume.
**Step 4.4 — Related patches**
- Record: Originally part of a 6-patch series but maintainer confirmed
v2 is standalone with no code changes from v1. No other series patches
required.
**Step 4.5 — Stable list history**
- Record: No stable-list discussion found for this specific fix.
Precedent: JMB394 quirk (`efb9e0f4f4378`) was explicitly nominated for
stable.
---
## Phase 5: Code Semantic Analysis
**Step 5.1 — Key functions**
- Record: `sata_pmp_quirks()` (modified), called from
`sata_pmp_attach()`
**Step 5.2 — Callers**
- Record:
- `sata_pmp_attach()` defined in `libata-pmp.c`, called from `libata-
eh.c` during error-handling/recovery when attaching a PMP device
- Triggered during SATA PMP enumeration at boot or hot-plug
**Step 5.3 — Callees**
- Record: Uses `sata_pmp_gscr_vendor()`, `sata_pmp_gscr_devid()`,
`ata_for_each_link()` — all standard libata PMP helpers
**Step 5.4 — Reachability**
- Record: Triggered whenever a JMicron JMS562 PMP is detected. Affects
boot path for systems using QNAP QDA-A2AR as root storage. Not
userspace-triggerable directly, but affects every boot on affected
hardware.
**Step 5.5 — Similar patterns**
- Record: Identical quirk pattern already used for JMB350 (`0x2352`) and
JMB394 (`0x0325`) in the same function. Same vendor, same flags, same
failure mode (SRST breaks detection).
---
## Phase 6: Cross-Reference Against Local Tree
**Step 6.1 — Buggy code present?**
- Record:
- Local tree: **v6.18.44** (`git describe HEAD`)
- Commit `c62aff1174cf8` is **NOT** in this tree (`git merge-base
--is-ancestor` → NOT)
- Buggy code **exists**: lines 460–472 of `drivers/ata/libata-pmp.c`
have JMicron quirk without `0x0562`
- JMicron quirk infrastructure present since v3.x era; bug is absence
of device ID, not post-branch regression
**Step 6.2 — Backport complications**
- Record: Clean apply confirmed (`git apply --check` passes). No
conflicting changes to this hunk in v6.18.y. Expected difficulty:
**clean apply**.
**Step 6.3 — Related fixes already present?**
- Record: No existing fix for JMS562 in this tree. `git log
--grep="JMS562"` returns nothing.
---
## Phase 7: Subsystem and Maintainer Context
**Step 7.1 — Subsystem**
- Record: `drivers/ata/` — libata PMP (Port Multiplier). Criticality:
**IMPORTANT** (storage/boot path for affected hardware).
**Step 7.2 — Activity**
- Record: Mature subsystem with occasional quirk additions. PMP quirk
table is stable; changes are typically small device-ID additions.
---
## Phase 8: Impact and Risk Assessment
**Step 8.1 — Who is affected**
- Record: Users of QNAP QDA-A2AR RAID1 adapters (JMicron JMS562 PMP)
booting from or accessing RAID volumes during rebuild. Driver-
specific, but impact is total for those users (unbootable system).
**Step 8.2 — Trigger conditions**
- Record: Boot or PMP attach while JMS562-managed RAID array is
rebuilding. Reproducible on affected hardware per commit message. Not
timing-dependent race — deterministic behavior mismatch.
**Step 8.3 — Failure severity**
- Record: Link disabled → storage unavailable → root filesystem not
found. **Severity: CRITICAL** for affected users (unbootable system,
potential data access loss during recovery window).
**Step 8.4 — Risk-benefit**
- Record:
- **Benefit: HIGH** — restores bootability on real hardware with
documented failure mode
- **Risk: VERY LOW** — 7-line quirk addition, scoped to one PCI device
ID, mirrors existing proven quirk
- **Ratio: Strongly favors backport**
---
## Phase 9: Final Synthesis
**Step 9.1 — Evidence summary**
FOR backport:
- Real hardware bug with concrete dmesg and boot failure
- Hardware quirk/workaround — explicit stable exception category
- Small, surgical, obviously correct
- Reviewed by libata maintainer
- Applies cleanly to v6.18.44
- Standalone, no dependencies
- Precedent: prior JMicron PMP quirks backported to stable
AGAINST backport:
- Affects narrow hardware population (QNAP QDA-A2AR users)
- No syzbot/security angle
- No explicit stable nomination
UNRESOLVED: None material to the decision.
**Step 9.2 — Stable rules checklist**
1. Obviously correct and tested? **PASS** — extends existing quirk;
reviewed by maintainer
2. Fixes real bug affecting users? **PASS** — boot failure on QNAP
QDA-A2AR
3. Important issue? **PASS** — unbootable system / root FS unavailable
(CRITICAL for affected users)
4. Small and contained? **PASS** — 7 lines, one file
5. No new features or APIs? **PASS** — device quirk only
6. Can apply to local tree? **PASS** — clean apply verified;
prerequisite code present
**Step 9.3 — Exception category**
- Record: **Hardware quirk/workaround** — adding device ID `0x0562` to
existing JMicron PMP quirk table
**Step 9.4 — Decision rationale**
This commit adds the JMicron JMS562 (`0x0562`) to an existing, well-
tested PMP quirk block in `sata_pmp_quirks()`. Without it, libata's
softreset and link-recovery logic on the QNAP QDA-A2AR adapter can
disable the fan-out link during RAID rebuild, preventing the root
filesystem from appearing at boot. The fix is minimal, matches the
pattern used for other JMicron chips since 2011, applies cleanly to the
v6.18.44 tree, and was reviewed by the libata maintainer. This is
textbook stable material: a hardware-specific workaround for a serious,
reproducible boot failure.
---
## Verification
- [Phase 1] Parsed commit `c62aff1174cf8`: subject, body, tags
(Reviewed-by: Damien Le Moal; no Fixes/Reported-by/stable tags)
- [Phase 2] Diff: +6/-1 in `sata_pmp_quirks()`, adds `devid == 0x0562`
to JMicron quirk
- [Phase 3] `git blame -L 460,472`: quirk block from 2011/2014 commits;
JMS562 not present
- [Phase 3] `git show efb9e0f4f4378`: JMB394 quirk had `Cc:
stable@vger.kernel.org`
- [Phase 3] `git merge-base --is-ancestor c62aff1174cf8 HEAD`: commit
NOT in tree
- [Phase 3] `git apply --check` on commit diff: applies cleanly
- [Phase 4] `b4 dig -c c62aff1174cf8`: found lore thread
- [Phase 4] `b4 dig -a`: v1 as patch 6/6, v2 standalone (committed
version)
- [Phase 4] `b4 dig -w`: CC'd dlemoal, cassel, linux-ide
- [Phase 4] mbox: Damien Le Moal Reviewed-by, no NAKs, v2 confirmed
standalone
- [Phase 5] `grep sata_pmp_attach`: caller in `libata-eh.c:3379`
- [Phase 5] Read `include/linux/libata.h`: confirmed flag meanings for
NO_SRST, ASSUME_ATA, NO_LPM
- [Phase 6] `git describe HEAD`: v6.18.44
- [Phase 6] Read `drivers/ata/libata-pmp.c:460-472`: buggy code (missing
0x0562) confirmed present
- [Phase 6] `git log v6.18..master -- drivers/ata/libata-pmp.c`: only
this commit touches quirk block
- [Phase 8] Commit message dmesg: softreset failure → link disabled →
root FS not found
**YES**
drivers/ata/libata-pmp.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 48ac09d9031e6..299b1823e0d09 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -457,8 +457,13 @@ static void sata_pmp_quirks(struct ata_port *ap)
* otherwise. Don't try hard to recover it.
*/
ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY;
- } else if (vendor == 0x197b && (devid == 0x2352 || devid == 0x0325)) {
+ } else if (vendor == 0x197b &&
+ (devid == 0x0562 || devid == 0x2352 || devid == 0x0325)) {
/*
+ * 0x0562: JMicron JMS562, as used in QNAP QDA-A2AR RAID1
+ * adapters. The exported device may stay not ready
+ * while the array is rebuilding, and SRST/classify can
+ * time out before the RAID volume is exported.
* 0x2352: found in Thermaltake BlackX Duet, jmicron JMB350?
* 0x0325: jmicron JMB394.
*/
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH AUTOSEL 6.18-5.10] ata: ahci: fail probe if BAR too small for claimed ports
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-5.10] ata: ahci: fail probe if BAR too small for claimed ports Sasha Levin
@ 2026-08-31 14:46 ` sashiko-bot
2026-09-02 8:40 ` Niklas Cassel
0 siblings, 1 reply; 7+ messages in thread
From: sashiko-bot @ 2026-08-31 14:46 UTC (permalink / raw)
To: Sasha Levin; +Cc: linux-ide, dlemoal, cassel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] The BAR size validation incorrectly assumes the maximum port index is bounded by HOST_CAP.NP, but the driver actually accesses ports up to fls(HOST_PORTS_IMPL), allowing out-of-bounds MMIO accesses to bypass the check.
- [High] The BAR size validation relies strictly on HOST_CAP.NP and rejects the device if the BAR is smaller than required for the maximum claimable ports, which can break working devices.
--
commit 93586245aa8cac6edeb231c78f24de78d4e9a254
Author: liyouhong <liyouhong@kylinos.cn>
Subject: ata: ahci: fail probe if BAR too small for claimed ports
This patch adds validation in ahci_init_one() to check if the BAR size is
sufficient for the number of ports claimed in HOST_CAP.NP. If the required
size exceeds the actual BAR size, the probe fails with -ENODEV to prevent
kernel panics from out-of-bounds MMIO access.
Link: https://lore.kernel.org/all/20260422080322.1006592-1-dayou5941@163.com/
> diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
> index 7a7f88b3fa2b1..bbf6e83abd880 100644
> --- a/drivers/ata/ahci.c
> +++ b/drivers/ata/ahci.c
> @@ -1874,6 +1874,24 @@ static ssize_t remapped_nvme_show(struct device *dev,
>
> static DEVICE_ATTR_RO(remapped_nvme);
>
> +static int ahci_validate_bar_size(struct pci_dev *pdev, int bar,
> + struct ahci_host_priv *hpriv)
> +{
> + u32 cap = readl(hpriv->mmio + HOST_CAP);
> + unsigned int max_ports = ahci_nr_ports(cap);
> + u32 last_port_end = 0x100 + (max_ports * 0x80);
[Severity: High]
Does this validation actually prevent all out-of-bounds MMIO accesses?
The validation uses HOST_CAP.NP (via ahci_nr_ports) to determine the required
BAR size, ignoring the actually implemented ports in HOST_PORTS_IMPL.
Looking at ahci_save_initial_config(), it only clears port_map if the total
count of set bits (map_ports) exceeds CAP.NP:
drivers/ata/libahci.c:ahci_save_initial_config() {
...
if (map_ports > ahci_nr_ports(cap)) {
dev_warn(dev,
"implemented port map (0x%lx) contains more ports than nr_ports (%u), using nr_ports\n",
port_map, ahci_nr_ports(cap));
port_map = 0;
}
...
}
If a controller reports CAP.NP = 0 (1 port) but sets bit 31 in HOST_PORTS_IMPL,
map_ports is 1. Since 1 > 1 is false, port_map is not cleared.
The loop will then execute for index 31, accessing MMIO out of bounds:
drivers/ata/libahci.c:ahci_save_initial_config() {
...
for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
if (hpriv->saved_port_cap[i])
continue;
port_mmio = __ahci_port_base(hpriv, i);
...
}
If the BAR size is 0x200, ahci_validate_bar_size() allows the probe to
continue (since max_ports is 1, and 0x180 < 0x200), resulting in an OOB access
and the exact panic this patch intended to prevent.
> + resource_size_t bar_size = pci_resource_len(pdev, bar);
> +
> + if (last_port_end > bar_size) {
> + dev_warn(&pdev->dev,
> + "BAR%d too small for %u ports (last port ends at %#x, BAR %pa)\n",
> + bar, max_ports, last_port_end, &bar_size);
> + return -ENODEV;
[Severity: High]
Could this strict validation break working devices?
If a device's generic IP block hardcodes CAP.NP to 31 (claiming 32 ports,
requiring a 0x1100 byte BAR), but the manufacturer only implemented 2 ports
(reflected in HOST_PORTS_IMPL) and mapped a standard 4KB (0x1000 byte) BAR,
the validation will fail (0x1100 > 0x1000).
Before this patch, the driver correctly relied on HOST_PORTS_IMPL to determine
which ports to access and safely initialized within the 4KB BAR. This patch
introduces a strict check that rejects the device if the BAR is smaller than
required for the maximum claimable ports in CAP.NP.
Should this warn instead of failing the probe entirely, or base the check on
the maximum port actually enabled in HOST_PORTS_IMPL?
> + }
> +
> + return 0;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831133314.4125787-166-sashal@kernel.org?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH AUTOSEL 6.18-5.10] ata: ahci: fail probe if BAR too small for claimed ports
2026-08-31 14:46 ` sashiko-bot
@ 2026-09-02 8:40 ` Niklas Cassel
0 siblings, 0 replies; 7+ messages in thread
From: Niklas Cassel @ 2026-09-02 8:40 UTC (permalink / raw)
To: sashiko-reviews; +Cc: Sasha Levin, linux-ide, dlemoal
On Mon, Aug 31, 2026 at 02:46:31PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> - [High] The BAR size validation incorrectly assumes the maximum port index is bounded by HOST_CAP.NP, but the driver actually accesses ports up to fls(HOST_PORTS_IMPL), allowing out-of-bounds MMIO accesses to bypass the check.
> - [High] The BAR size validation relies strictly on HOST_CAP.NP and rejects the device if the BAR is smaller than required for the maximum claimable ports, which can break working devices.
> --
>
> commit 93586245aa8cac6edeb231c78f24de78d4e9a254
> Author: liyouhong <liyouhong@kylinos.cn>
> Subject: ata: ahci: fail probe if BAR too small for claimed ports
>
> This patch adds validation in ahci_init_one() to check if the BAR size is
> sufficient for the number of ports claimed in HOST_CAP.NP. If the required
> size exceeds the actual BAR size, the probe fails with -ENODEV to prevent
> kernel panics from out-of-bounds MMIO access.
>
> Link: https://lore.kernel.org/all/20260422080322.1006592-1-dayou5941@163.com/
>
> > diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
> > index 7a7f88b3fa2b1..bbf6e83abd880 100644
> > --- a/drivers/ata/ahci.c
> > +++ b/drivers/ata/ahci.c
> > @@ -1874,6 +1874,24 @@ static ssize_t remapped_nvme_show(struct device *dev,
> >
> > static DEVICE_ATTR_RO(remapped_nvme);
> >
> > +static int ahci_validate_bar_size(struct pci_dev *pdev, int bar,
> > + struct ahci_host_priv *hpriv)
> > +{
> > + u32 cap = readl(hpriv->mmio + HOST_CAP);
> > + unsigned int max_ports = ahci_nr_ports(cap);
> > + u32 last_port_end = 0x100 + (max_ports * 0x80);
>
> [Severity: High]
> Does this validation actually prevent all out-of-bounds MMIO accesses?
>
> The validation uses HOST_CAP.NP (via ahci_nr_ports) to determine the required
> BAR size, ignoring the actually implemented ports in HOST_PORTS_IMPL.
>
> Looking at ahci_save_initial_config(), it only clears port_map if the total
> count of set bits (map_ports) exceeds CAP.NP:
>
> drivers/ata/libahci.c:ahci_save_initial_config() {
> ...
> if (map_ports > ahci_nr_ports(cap)) {
> dev_warn(dev,
> "implemented port map (0x%lx) contains more ports than nr_ports (%u), using nr_ports\n",
> port_map, ahci_nr_ports(cap));
> port_map = 0;
> }
> ...
> }
>
> If a controller reports CAP.NP = 0 (1 port) but sets bit 31 in HOST_PORTS_IMPL,
> map_ports is 1. Since 1 > 1 is false, port_map is not cleared.
1) A controller that reports CAP.NP, but does not have a BAR size to accomodate
that amount of ports, would already have been rejected in ahci_init_one(),
so ahci_save_initial_config() would never even get called.
2) Having bit 31 set in the PI register, would require CAP.NP to have a value
of at least 31 (meaning 32 ports, since it is zeroes based).
See the register description of the PI register:
3.1.4 Offset 0Ch: PI – Ports Implemented
This register indicates which ports are exposed by the HBA. It is loaded by
the BIOS. It indicates which ports that the HBA supports are available for
software to use. For example, on an HBA that supports 6 ports as indicated
in CAP.NP, only ports 1 and 3 could be available, with ports 0, 2, 4, and 5
being unavailable.
Software must not read or write to registers within unavailable ports.
The intent of this register is to allow system vendors to build platforms
that support less than the full number of ports implemented on the HBA
silicon.
Thus, AFAICT, having a bit set in the PI register that is higher than CAP.NP,
would be violating the spec.
>
> The loop will then execute for index 31, accessing MMIO out of bounds:
>
> drivers/ata/libahci.c:ahci_save_initial_config() {
> ...
> for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
> if (hpriv->saved_port_cap[i])
> continue;
>
> port_mmio = __ahci_port_base(hpriv, i);
> ...
> }
>
> If the BAR size is 0x200, ahci_validate_bar_size() allows the probe to
> continue (since max_ports is 1, and 0x180 < 0x200), resulting in an OOB access
> and the exact panic this patch intended to prevent.
>
> > + resource_size_t bar_size = pci_resource_len(pdev, bar);
> > +
> > + if (last_port_end > bar_size) {
> > + dev_warn(&pdev->dev,
> > + "BAR%d too small for %u ports (last port ends at %#x, BAR %pa)\n",
> > + bar, max_ports, last_port_end, &bar_size);
> > + return -ENODEV;
>
> [Severity: High]
> Could this strict validation break working devices?
>
> If a device's generic IP block hardcodes CAP.NP to 31 (claiming 32 ports,
> requiring a 0x1100 byte BAR), but the manufacturer only implemented 2 ports
> (reflected in HOST_PORTS_IMPL) and mapped a standard 4KB (0x1000 byte) BAR,
> the validation will fail (0x1100 > 0x1000).
>
> Before this patch, the driver correctly relied on HOST_PORTS_IMPL to determine
> which ports to access and safely initialized within the 4KB BAR. This patch
> introduces a strict check that rejects the device if the BAR is smaller than
> required for the maximum claimable ports in CAP.NP.
>
> Should this warn instead of failing the probe entirely, or base the check on
> the maximum port actually enabled in HOST_PORTS_IMPL?
Yes, a device's generic IP block hardcodes CAP.NP to some value (the number
of ports theoretically supported by the hardware), and then a manufacturer
can chose to only implement certain ports (using the PI register).
If the manufacturer did not have the ability to change CAP.NP, I doubt
that they will have the ability to change the size of the BAR, which should
be determined by the device's generic IP block, and should have a size that
can accomodate CAP.NP.
While the spec says:
"Software must not read or write to registers within unavailable ports."
Not having a BAR that is not enough to accomodate CAP.NP seems very wrong.
If we ever find such a controller, I would prefer to quirk that controller
to simply override (the obviously bogus) CAP.NP.
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-09-02 8:40 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260831133314.4125787-1-sashal@kernel.org>
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-5.10] ata: ahci: fail probe if BAR too small for claimed ports Sasha Levin
2026-08-31 14:46 ` sashiko-bot
2026-09-02 8:40 ` Niklas Cassel
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.12] ata: libata-core: Disable LPM on some WD drives Sasha Levin
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-6.12] ata: libata-core: Disable LPM on WD Green 2.5 480GB Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.12] ata: libata-core: Disable LPM on WDC WD141KFGX-68FH9N0 Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-5.10] ata: libata-pmp: add JMicron JMS562 quirk Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox