Skip to content

Let the kernel control PCIe ASPM, restoring UEFI deploy throughput - #146

Merged
mastacontrola merged 4 commits into
masterfrom
pcie-aspm-realtek-rx-throughput
Aug 6, 2026
Merged

Let the kernel control PCIe ASPM, restoring UEFI deploy throughput#146
mastacontrola merged 4 commits into
masterfrom
pcie-aspm-realtek-rx-throughput

Conversation

@mastacontrola

Copy link
Copy Markdown
Member

Fixes the ~10x UEFI deploy slowdown reported on forums topic 18212 — Dell OptiPlex 3070, RTL8168h rev 15, kernel 6.18.38 / init 20260804. Deploy ran ~1.2 GB/min under UEFI vs 6–10 GB/min legacy on the same machine, while capture still ran ~15 GB/min. Same chip and symptoms as Debian bug #1110193.

Root cause

CONFIG_PCIEASPM (all arches) and CONFIG_PCI_MMCONFIG (x64 only — x86 always had it) are default y upstream and have been off in FOS since b56b8d9 (2016).

That was harmless for nine years because the out-of-tree Realtek vendor drivers managed ASPM themselves — r8168 is built here with -DCONFIG_DYNAMIC_ASPM and disables ASPM whenever traffic is flowing. bc9ee24 (the #108 switch to in-kernel r8169) dropped those drivers and removed the cover. The reporter correctly identified that commit; it is the exposer, not the defect.

The trap. r8169 does not manage ASPM itself — it asks the PCI core once at probe:

rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);
tp->aspm_manageable = !rc;

With CONFIG_PCIEASPM=n that is an inline stub in include/linux/pci.h that returns 0 — success. r8169 therefore concludes the OS disabled L1, sets aspm_manageable, and in rtl_hw_start() goes on to enable ASPM, ClkReq, and — for exactly this chip's RTL_GIGA_MAC_VER_46/* chip can trigger L1.2 */. The driver switches ASPM on in the NIC believing the kernel has L1 off, on a kernel containing no ASPM code at all. Nothing is logged.

CONFIG_PCI_MMCONFIG compounds it: without it pci_ext_cfg_avail() returns 0, every device's cfg_size caps at 256 bytes, and the L1 PM Substates extended capability — where L1.1/L1.2 are actually controlled — is unreachable. That is what r8169's No native access to PCI extended config space, falling back to CSI notice is really reporting. Neither symbol is sufficient alone.

Why UEFI only, and why download only. ASPM is programmed by platform firmware; Dell's native UEFI path enables L1/L1.2 on the root port, the CSM path does not, and the kernel could correct neither. Deploy is client-receive: the link idles between the server's bursts, drops into L1.2, and pays the exit latency on every wake. Capture is client-transmit, host-driven and keeps the link busy — hence uploads were unaffected. Legacy was never faster; the firmware just happened to leave ASPM off.

Note that pcie_aspm=off on the kernel command line is a no-op on a FOS kernel — the __setup() registering it lives inside the #ifdef CONFIG_PCIEASPM. This could not be left to a kernel argument.

Change

Enables on all three arches:

CONFIG_PCIEASPM=y
CONFIG_PCIEASPM_DEFAULT=y

and on x64 (x86 already had it; arm64 has no such symbol and reaches extended config space through its own ECAM host controller):

CONFIG_PCI_MMCONFIG=y

Policy is DEFAULT rather than PERFORMANCE so each driver keeps making its own chip-specific call — r8169 honours rtl_aspm_is_safe() for boards whose vendor certified ASPM 1.2 — instead of blanket-overriding firmware on every link. PERFORMANCE is the documented escalation if other NICs turn out to have the same problem. The power-saving policies are rejected by the new harness; they would enable ASPM on links whose firmware left it off, and would have made this bug appear on legacy boots too.

Adds docs/adr/0011-pcie-aspm-and-extended-config-space.md and tests/checks/pcie-aspm-config.sh, and registers secureboot-config.sh in the test lists (it was missing from both).

Verification

  • All 7 tests/checks/ harnesses and the golden harness pass.
  • The new harness fails with 7 findings against the pre-fix configs, and correctly skips PCI_MMCONFIG on x86 (already set) and arm64 (not applicable).
  • Both symbols survive make olddefconfig on x64 — the ADR-0010 silent-drop trap.
  • The isolated post-oldconfig delta vs master is exactly these symbols plus the def_bool CONFIG_MMCONF_FAM10H, and nothing else.

Not yet validated on hardware

The throughput claim is derived from source, not measured. ADR-0011 records a read-only procedure that confirms or kills it in about a minute with no rebuild: from a FOS shell (pciutils ships in the init), compare setpci -s <bdf> CAP_EXP+10.w on the NIC and its root port booted UEFI vs legacy. Prediction: UEFI reads back 2 or 3, legacy reads 0.

Refs: #108

mastacontrola and others added 4 commits August 5, 2026 07:02
Deploys onto a Dell OptiPlex 3070 (RTL8168h rev 15) run at ~1.2 GB/min under
UEFI against 6-10 GB/min on the same machine booted legacy, while captures
still run at ~15 GB/min. Forums topic 18212; same chip and symptoms as Debian
bug #1110193.

CONFIG_PCIEASPM and CONFIG_PCI_MMCONFIG are `default y` upstream and have been
off in FOS since b56b8d9 (2016). Nothing noticed for nine years because the
out-of-tree Realtek vendor drivers managed ASPM themselves -- r8168 is built
here with -DCONFIG_DYNAMIC_ASPM and switches ASPM off whenever traffic is
flowing. bc9ee24 dropped those drivers for the in-kernel r8169 and removed the
cover.

r8169 does not manage ASPM itself; it asks the PCI core once at probe. With
CONFIG_PCIEASPM=n, pci_disable_link_state() is an inline stub that RETURNS
SUCCESS, so r8169 sets tp->aspm_manageable = true, concludes the OS disabled
L1, and then enables ASPM, ClkReq and -- for exactly this chip's
RTL_GIGA_MAC_VER_46 -- L1.2 triggering in the NIC. Nothing is logged. The link
drops into L1.2 between the server's bursts and pays the exit latency on every
wake, which is why only the receive direction is affected.

CONFIG_PCI_MMCONFIG compounds it: without it pci_ext_cfg_avail() returns 0,
cfg_size is capped at 256 bytes, and the L1 PM Substates extended capability
where L1.1/L1.2 actually live is unreachable. That is also what r8169's "No
native access to PCI extended config space, falling back to CSI" notice is
reporting. Neither symbol is sufficient alone.

This could not be left to a kernel argument: with CONFIG_PCIEASPM=n the
__setup() registering `pcie_aspm=off` is compiled out, so the usual field
workaround is a silent no-op on a FOS kernel.

Policy is DEFAULT rather than PERFORMANCE, so each driver keeps making its own
chip-specific call (r8169 honours rtl_aspm_is_safe() for vendor-certified
boards) instead of blanket-overriding firmware on every link. The power-saving
policies are rejected by the new harness -- they would enable ASPM on links
whose firmware left it off, and would have made this bug appear on legacy
boots too.

Verified that both symbols survive `make olddefconfig` on x64 (the ADR-0010
silent-drop trap) and that the isolated post-oldconfig delta is exactly these
symbols plus the def_bool CONFIG_MMCONF_FAM10H.

Not yet validated on hardware -- ADR-0011 records a read-only setpci procedure
that confirms or kills the diagnosis in a minute without a rebuild.

Refs: #108
The recorded procedure cleared the whole Link Control register and did the
root port before the endpoint. Both are wrong:

- A bare CAP_EXP+10.w=0000 also clears Common Clock Configuration, Clock PM
  and Extended Sync. Clearing CCC on a live link without a retrain is its own
  problem, so the write is now masked to the ASPM Control bits (0000:0003).
- PCIe r6.2 sec 7.5.3.7 requires ASPM L1 to be disabled in the Downstream
  component before the Upstream one; pcie_config_aspm_link() in
  drivers/pci/pcie/aspm.c does exactly that. Endpoint now goes first.

Diagnostic-only change; no effect on the config fix itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…d herring

Validated on the reporter's OptiPlex 3070 (RTL8168h rev 15): UEFI deploy
~1.2 -> ~6.5 GB/min with EXP_20260805-123232, legacy unchanged.

Two things the status now says explicitly:

- The setpci Link Control comparison was never run, so the claim that Dell's
  UEFI firmware enables L1 where its CSM path does not is still an inference.
  The fix working does not prove the mechanism behind the UEFI/legacy split.
- 'tx checksumming: ko' is r8169's probe-time jumbo capability note, keyed on
  tp->mac_version alone and printed regardless of MTU. It was never a second
  bug, and kernels with this fix print the same line -- worth naming so nobody
  reads a later 'ko' as a regression.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
master gained its own ADR-0011 (UKI feasibility) and an 0012 while this branch
was out, so the PCIe ASPM ADR collided on 0011. Renumbered to 0013 and updated
its references in CLAUDE.md, tests/README.md and the check harness header --
same cleanup GH-143 did for the duplicate 0009.

The CLAUDE.md conflict was purely additive on both sides: both branches
appended a bullet to the invariants list. Kept both, with PCIe ASPM moved
after 0012.

Also corrected the throughput figure from the '~10x' estimate to the ~5x
actually measured on hardware (1.2 -> 6.5 GB/min).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@mastacontrola
mastacontrola merged commit cf9490c into master Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant