fix(talos): add pcie_port_pm=off for Arc B70 root-port race - #1487
Merged
Conversation
The Arc Pro B70 disappeared from talos-3 because Linux runtime-suspended the OCuLink root port 00:01.0 to D3hot 218 ms into boot, while bus 01 was still empty. The card finished training afterwards (Gen4 x4, equalization complete on all 3 phases, real link partner), but SLTCAP HotPlugCapable=0 and SLTCTL=0x0000 mean every hotplug and link-state interrupt is disabled, so a port that sleeps before its device answers can never rediscover it. pcie_aspm=off was already present and does not cover this: it governs ASPM link power states, not runtime D-state suspension of the port itself. Verified against Linux v6.18 (nodes run 6.18.44-talos): - Documentation/admin-guide/kernel-parameters.txt:5082 documents pcie_port_pm= with "off - Disable power management of all PCIe ports". - drivers/pci/pci.c:173 pcie_port_pm_setup() sets pci_bridge_d3_disable, which makes pci_bridge_d3_possible() return false for PCI_EXP_TYPE_ROOT_PORT (pci.c:2998), so drivers/pci/pcie/portdrv.c never reaches pm_runtime_allow() for the port. The schematic is cluster-wide, so all three nodes get the argument. Only talos-3 has the affected card; the others pick it up on their next reboot. The tradeoff is marginally higher idle power from PCIe ports staying in D0. File change only. Kernel args ride in the factory schematic, so this needs `just talos upgrade-node talos-3` (talosctl upgrade -m powercycle) to take effect - `apply-node` only stages machine config. That attended reboot is the captain's to time; runbook lands in docs/hardware-incidents.md.
… reboot runbook docs/hardware-incidents.md [2026-08-24] recorded the power-on-order fix but never recorded that it worked. Three additions to that entry: 1. Confirmed recovered. talos-3 booted 2026-08-26T11:21:12Z with the B70 enumerated and has held stable under production load for three days, with every failure signature in the Evidence table cleared (e2ff/e223 present, xe bound, 00:01.0 back in D0/active with runtime_suspended_time=0, bus 01-04 populated, NICs back on enp6s0f*). 182 W live draw with vllm serving. 2. The pcie_port_pm=off mitigation, stated honestly: it prevents the race on future boots, it is not retroactive, and it does not remove the need for the dock-PSU-first power-on order once a card is already lost. Includes why pcie_aspm=off never covered this (link states vs port D-state) and the Linux v6.18 source references. 3. Runbook for the single attended reboot that activates it: Ceph safety gate, PCIe baseline capture, `just talos upgrade-node talos-3`, the dock-PSU-first recovery if the card does not return, and the verification commands. Notes the reboot also carries e22cfb2 (#1479, thunderbolt drop) by deliberate sequencing, and that it doubles as the test of the mitigation so the outcome is worth recording back. Every runbook command was verified read-only against the live node. Also adds pointers where an operator will actually hit them: the root AGENTS.md pre-reboot checklist, and talos/AGENTS.md. The latter also gains the distinction that schematic.yaml.j2 changes need `upgrade-node`, not `apply-node` - kernel args are baked into the Image Factory image, so an `apply-node`d schematic change silently does nothing.
talos-3 runs schematic b1a6b2ff (#1444) and still has thunderbolt loaded. main is 7f25ace8 (thunderbolt dropped, e22cfb2/#1479) and this change is a46161e7 (thunderbolt dropped plus pcie_port_pm=off), so the single attended reboot closes both gaps at once. IDs confirmed against factory.talos.dev and the live node's ExtensionStatus; upgrade-node still derives the target itself, so they are for confirmation only.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Close the PCIe runtime power-management race that made the Arc Pro B70 disappear from talos-3, by adding one kernel argument to the schematic; also record that the existing operational fix was confirmed to work, and write the runbook for the single attended reboot that will activate this.
SCOPE CONSTRAINT (explicit, from the requester): ship the CODE CHANGE ONLY. Do NOT upgrade, reboot, powercycle, drain, apply config to any node, or change any workload. That step is the captain's, timed by him. If the change appears unvalidatable without one, that is a decision to escalate, not to perform. No node was touched during this work: verified read-only that the card is still healthy, the live schematic is still b1a6b2ff, and uptime is unbroken.
MECHANISM (authoritative record: docs/hardware-incidents.md:9-64). At boot the link was down. pcie_failed_link_retrain() retrained at 2.5 GT/s and failed, and the scan of bus 01 found nothing. 218 ms in, with zero children, Linux runtime-suspended 00:01.0 to D3hot. The card then finished training properly (Gen4 x4, equalization complete on all three phases, real link partner). Nothing could ever notice, because SLTCAP HotPlugCapable=0 and SLTCTL=0x0000 disable every hotplug and link-state interrupt; a root port that cannot report a late-arriving device cannot self-heal. Separately, SLTCAP PowerController=0 is why cycling host power does not cycle the dock's PSU, which is why the 2026-08-24 host power cycle did not recover it.
THE CHANGE: add pcie_port_pm=off to extraKernelArgs in talos/schematic.yaml.j2, with a comment in the same style as its neighbours explaining what it does and why, pointing at docs/hardware-incidents.md.
VERIFICATION REQUIREMENT (explicitly demanded before writing it): confirm pcie_port_pm is a real parameter for the kernel Talos actually ships (6.18.x) and that 'off' is the correct value, from kernel documentation or source rather than from the request. Done: nodes run 6.18.44-talos; Linux v6.18 Documentation/admin-guide/kernel-parameters.txt:5082 documents pcie_port_pm= with 'off' = 'Disable power management of all PCIe ports'; drivers/pci/pci.c:173 pcie_port_pm_setup() sets pci_bridge_d3_disable, which makes pci_bridge_d3_possible() return false for PCI_EXP_TYPE_ROOT_PORT (pci.c:2998), so drivers/pci/pcie/portdrv.c:719 never reaches pm_runtime_allow() for the port. That chain is exactly the observed failure mode.
DELIBERATE COMMENT CONTENT: the comment must say that the schematic already carries pcie_aspm=off, which disables PCIe LINK power states but does NOT stop the PORT runtime-suspending itself to D3hot, because that distinction is the reason this failure survived an argument that looks like it should have caught it.
DO NOT TOUCH pcie_aspm=off, pci=realloc, or pci=assign-busses - they are load-bearing for this same GPU path. (Verified still intact.)
DOCUMENTATION WORK FOLDED IN, as requested:
RUNBOOK REQUIREMENTS: kernel args are not activated by 'just talos apply-node', which only stages config; they need 'just talos upgrade-node talos-3', which is talosctl upgrade -m powercycle (confirmed against talos/mod.just rather than taken on trust). That reboot is the risk event and is also when talos-3 picks up e22cfb2 from PR #1479 dropping siderolabs/thunderbolt; the captain deliberately sequenced them into one maintenance window. The runbook states: capture the GPU's PCIe state before, so there is a baseline; the host powercycle does not cycle the dock PSU, so if the card does not return the recovery is the documented power-on order (dock PSU first, wait 5-10 seconds, confirm fans and LED, then the host; never together, never host-first); exactly how to verify success afterwards (8086:e2ff and 8086:e223 present, xe bound, 00:01.0 in D0, node advertising its GPU resource again); and that this reboot doubles as the test of whether the mitigation works, so the result is worth recording back into the incident doc. Every runbook command was verified read-only against the live node.
ACCEPTED TRADEOFF, to state plainly in the PR description so nobody is surprised: the schematic is cluster-wide, so this argument reaches every node. Only talos-3 has the affected card; it takes the argument in the attended maintenance, and the others pick it up on their next natural reboot. Cost is marginally higher idle power from PCIe ports staying in D0.
ADDITIONAL WORK I JUDGED IN SCOPE (not explicitly requested, flagged for review):
VALIDATION ALREADY RUN LOCALLY: scripts/ci/talos-validate.sh and scripts/ci/version-consistency.sh (the only two gates that read the changed files) both pass. Four python regression tests fail on missing litellm/hcl2 modules; those test files are byte-identical to the base commit and unrelated to a Talos/docs change, so they are pre-existing environmental gaps, not regressions.
STYLE CONSTRAINT: this repo's owner requires plain dash '-' and never the em dash character in authored text; verified zero em dashes in all added lines.
What Changed
pcie_port_pm=offtotalos/schematic.yaml.j2extraKernelArgs(with comment clarifying why existingpcie_aspm=offdoes not cover port runtime D3hot) so late-training PCIe devices are not orphaned when a root port suspends before link-up.just talos upgrade-node talos-3runbook indocs/hardware-incidents.md, with cross-links fromAGENTS.md,talos/AGENTS.md, anddocs/ai-gpu-changelog.md; also corrects apply-node vs upgrade-node guidance for schematic/kernel-arg changes.scripts/ci/schematic-pcie-port-pm-test.pyto assert the rendered schematic keepspcie_port_pm=offplus the load-bearing GPU path args and round-trips that contract through factory.talos.dev.Tradeoff: the schematic is cluster-wide, so all nodes get the arg; only talos-3 needs it for the B70. Cost is marginally higher idle power from PCIe ports staying in D0. Activation remains an attended captain-run
upgrade-node(not part of this PR).Risk Assessment
✅ Low: Single well-documented cluster-wide kernel arg with matching runbook and no live node operations; residual activation risk is explicitly deferred to the captain's attended upgrade-node window.
Testing
Exercised the offline operator path only: rendered the schematic, confirmed pcie_port_pm=off plus preserved pcie_aspm/pci=realloc/pci=assign-busses, posted it to factory.talos.dev (id a46161e7…, base 7f25ace8…), verified Linux v6.18 documents off as disabling PCIe port PM, and re-ran talos-validate plus version-consistency green. Added and ran schematic-pcie-port-pm-test.py with a failing negative control. No node upgrade/reboot was performed, matching the explicit scope constraint.
Evidence: schematic-pcie-port-pm-test.py pass
OK: schematic renders with pcie_port_pm=off and load-bearing GPU args; factory id a46161e7… stores the same contractEvidence: negative control without pcie_port_pm=off
NEGATIVE_OK: extraKernelArgs missing required entries ['pcie_port_pm=off']Evidence: rendered schematic YAML
Evidence: factory-stored schematic (includes pcie_port_pm=off)
Evidence: branch schematic id a46161e7…
a46161e7a33fbde0589543ccc42a80403294ffd09868d4a09c10df0b64732021Evidence: base schematic id 7f25ace8…
7f25ace820d39f0048bfd5fc6cdf882c6af2410f229d495ed2ff384c4c6807b8Evidence: Linux v6.18 pcie_port_pm kernel parameter docs
pcie_port_pm= [PCIE] PCIe port power management handling: off Disable power management of all PCIe ports force Forcibly enable power management of all PCIe portsEvidence: Linux v6.18 pcie_port_pm_setup source
Evidence: talos-validate.sh
OK: 3 node config(s) render and validate; schematic rendersEvidence: version-consistency.sh
OK: 6 machineconfig version pin(s) match the tuppr CRs (Talos v1.13.9, Kubernetes v1.36.3)Evidence: evidence summary
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
MINIJINJA_CONFIG_FILE=.minijinja.toml scripts/ci/talos-validate.shscripts/ci/version-consistency.shpython3 scripts/ci/schematic-pcie-port-pm-test.py(render + parse extraKernelArgs + factory.talos.dev POST/GET round-trip)negative control: same test asserts failure whenpcie_port_pm=offis stripped from rendered argsfactory schematic id check: brancha46161e7…vs base7f25ace8…matches docs tableLinux v6.18 kernel-parameters +pcie_port_pm_setupsource confirmation thatoffsetspci_bridge_d3_disabletalos/mod.justupgrade-node recipe confirms-m powercycleand_schematic-idfactory POST pathdocs/hardware-incidents.md structure check for recovery confirmation, mitigation limits, and attended reboot runbook✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.