Linux Kernel Selftest development
 help / color / mirror / Atom feed
From: Priyank Rathod <rathodpriyank@google.com>
To: Bjorn Helgaas <bhelgaas@google.com>,
	Jonathan Corbet <corbet@lwn.net>,
	 Shuah Khan <skhan@linuxfoundation.org>,
	Randy Dunlap <rdunlap@infradead.org>,
	 Kees Cook <kees@kernel.org>,
	"Gustavo A. R. Silva" <gustavoars@kernel.org>
Cc: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
	linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
	"Priyank Rathod" <rathodpriyank@google.com>,
	sashiko-bot@kernel.org, linux-doc@vger.kernel.org,
	linux-kselftest@vger.kernel.org, linux-hardening@vger.kernel.org
Subject: [PATCH v2 0/3] PCI/pcie: Add PCIe Lane Margining at Receiver (LMR) support
Date: Fri, 04 Sep 2026 02:48:27 +0000	[thread overview]
Message-ID: <20260904-pcie-link-endpoints-v2-0-16fcb301a3e4@google.com> (raw)

Hi Bjorn, Ilpo, and the PCI community,

This patch series introduces upstream Linux kernel support for PCIe Lane Margining
at Receiver (LMR) per PCI Express Base Specification Revision 7.0 / 6.0 (§ 7.7.11
and § 8.4.4).

During the review of the previous v7 standalone LMR submission
(https://lore.kernel.org/linux-pci/20260828-pcie-lmt-v7-1-6012e9e0940a@google.com/),
Ilpo Järvinen pointed out that feature drivers resolving link partners duplicate
link traversal logic that is already present in drivers such as ASPM:

  "This feels like duplicating similar functionality with the aspm driver
   that also wants to infer ends of the link when giving a pci_dev in.
   The aspm driver currently does that within, but it kind of duplicating
   pci_bus. It would be nice to avoid the duplication and have something
   similar for this in PCI core."

In response to this feedback, the implementation is factored into a clean,
modular 3-patch stack:

1. Patch 1/3 (PCI: Add pcie_get_link_endpoints() helper):
   Standardized, race-safe helper in drivers/pci/pci.c and include/linux/pci.h
   to identify both ends of a point-to-point PCIe link. Safely inspects the
   subordinate bus under down_read(&pci_bus_sem) and acquires a reference
   (pci_dev_get()), paired symmetrically with pcie_put_link_endpoints().
   Filters for Function 0 (with ARI support), validates bridge ownership
   (child->self == pdev) to prevent ABA pointer reuse, and handles RCiEP
   and empty downstream ports (-ENODEV).

2. Patch 2/3 (PCI/ASPM: Add pci_aspm_inhibit() helper for temporary link state suppression):
   Reference-counted mechanism (aspm_inhibit_cnt) in drivers/pci/pcie/aspm.c
   to temporarily disable ASPM state transitions (L0s, L1, L1SS) on an active link.
   Guarantees callers hold down_read(&pci_bus_sem) (via lockdep_assert_held_read),
   eliminating deadlocks and preventing power-saving transitions while hardware
   link characterization is in progress.

3. Patch 3/3 (PCI/pcie: Add PCIe Lane Margining at Receiver (LMR) support):
   Implements the core LMR driver (CONFIG_PCIE_LMR) in drivers/pci/pcie/margin.c
   exposing a debugfs interface under /sys/kernel/debug/pci/pcie_lmr_<dev>/.
   Strictly self-contained: 0 modified lines in drivers/pci/pci.c, pci-driver.c,
   or core drivers/pci/pci.h. Exposes clean lifecycle hooks in drivers/pci/probe.c
   and drivers/pci/remove.c, supports 2D timing and voltage margining across
   physical receivers (0..6), enforces Function 0 endpoint filtering (§ 7.7.11),
   and includes an exhaustive kselftest suite (tools/testing/selftests/pcie_lmt/).

- Capability Discovery (§ 7.7.11): Probed via Extended Capability ID 0x27 on
  Gen4+ (>= 16 GT/s) physical links. Differentiates optional support on Gen4/Gen5
  from mandatory capability presence on Gen6+ (>= 64 GT/s).
- Multi-Function Device Scope (§ 7.7.11): Enforces that capability registration
  is strictly restricted to Function 0 on Endpoints / Upstream Ports.
- Payload Decoding (Table 4-77, Cmd 88h): Accurately decodes Margin Control
  Capabilities (Bits 0..4); preserves Bits 7:5 as reserved 0b.
- Direction Encodings (§ 4.2.18.1.2): Enforces that Left/Right and Up/Down
  direction bits remain 0b for symmetric receivers (Bits 6 & 7 reserved 0b).
- Multi-Receiver Concurrency (§ 4.2.18.2): Governed strictly by MIndErrorSampler.
  If MIndErrorSampler == 0b (main data sampler), at most one receiver across the
  link is margined at a time.
- Autonomous Speed & Width Transitions (§ 7.5.3.7, § 7.5.3.17, § 8.4.4): Software
  sequencing disables Downstream Component before Upstream Component on enablement,
  and restores Upstream Component before Downstream Component on teardown.
  Restoration is unconditional via pcie_capability_clear_and_set_word()
  (serialized by pci_lock), eliminating trylock failure traps.

Ingress paths (margin_enable_write and pci_lmr_exit) strictly follow the canonical
PCI locking DAG:
  down_read(&pci_bus_sem)
    -> pci_dev_lock(downstream_port)
      -> pci_dev_lock(upstream_port)
        -> mutex_lock(&mdev->lock)
          -> spin_lock_irqsave(&aspm_lock)

Key Concurrency Guarantees:
1. Hot-Swap Identity Invariance: When disabling LMR, dynamic endpoint resolution
   is completely bypassed. Teardown binds strictly to the session-saved mdev->partner,
   which is read and pinned with pci_dev_get() under mutex_lock(&mdev->lock).
2. Surprise Removal & Fault Hardening: Hardware register accesses check
   pci_dev_is_disconnected() and PCI_POSSIBLE_ERROR() guards, preventing MMIO
   or config space bus aborts when hardware is pulled.
3. Power Management Synchronization: Both link partners are pinned in D0 using
   pm_runtime_resume_and_get() during enablement, and symmetrically released via
   pm_runtime_put() on teardown. System suspend hooks into pci_pm_prepare() where
   all devices in the hierarchy are guaranteed to be in D0.
4. Security Teardown Order: In pci_destroy_dev(), pci_lmr_exit() is called after
   pci_tsm_destroy(), preserving D0 state for TSM link operations (PCIe IDE unbind
   and SPDM cryptographic session teardown).

- Build: Clean compile on x86_64 and ARM64; make W=1 drivers/pci/ (0 warnings).
- Linters: checkpatch.pl clean across all 3 patches (0 errors, 0 warnings).
- Kselftest: tools/testing/selftests/pcie_lmt/pcie_lmt.sh expanded to 287 lines,
  covering positive and negative boundary tests (syntax clean with bash -n).
- Pre-Commit AI Review (Sashiko AI):
  * Patch 1 (f34fdf7f5c6b): Reviewed — Clean (0 issues).
  * Patch 2 (6adc680a727f): Reviewed — Clean (0 issues).
  * Patch 3 (c62b5f92af63): Reviewed — Clean (0 issues, "No issues found.").

Signed-off-by: Priyank Rathod <rathodpriyank@google.com>
---
Changes in v2:
- Decomposed monolithic LMR driver into a 3-patch stack with dedicated core helpers:
  * Patch 1: PCI core link endpoint discovery helper (pcie_get_link_endpoints()).
  * Patch 2: Core ASPM temporary inhibition helper (pci_aspm_inhibit()).
  * Patch 3: PCIe Lane Margining at Receiver driver and debugfs interface.
- Core Scope Discipline: Confined LMR logic exclusively to drivers/pci/pcie/margin.c
  and include/linux/pci.h forward declarations (0 modified lines in pci.c/pci-driver.c).
- Endpoint Discovery Hardening:
  * Handled RCiEP and empty downstream buses returning -ENODEV.
  * Added Function 0 resolution (pcie_find_link_upstream_func0()) supporting PCIe ARI.
  * Added bridge ownership verification (child->self == pdev) to prevent ABA races.
  * Added symmetric pcie_put_link_endpoints() to balance pci_dev_get() references.
- ASPM Inhibit Hardening:
  * Added lockdep_assert_held_read(&pci_bus_sem) to pci_aspm_inhibit_locked().
  * Added reference counting (aspm_inhibit_cnt) to support nested/concurrent calls.
- Hot-Swap & Concurrency Protections:
  * Eliminated hot-swap identity mismatch in margin_enable_write() by binding teardown
    strictly to session-saved mdev->partner instead of re-evaluating endpoints.
  * Added mutex protection when reading and pinning mdev->partner to eliminate UAF races.
  * Converted autonomous speed/width restoration to unconditional register write via
    pcie_capability_clear_and_set_word(), eliminating trylock failure degradation.
- Specification Alignments (PCIe Base Spec r7.0):
  * Aligned Extended Capability ID 0x27 to § 7.7.11 and § 8.4.4.
  * Enforced Function 0 restriction on Endpoints / Upstream Ports (§ 7.7.11).
  * Preserved Reserved Bits 7:5 in Command 88h capabilities response.
  * Implemented MIndErrorSampler-based concurrency for multi-receiver links (§ 4.2.18.2).
  * Corrected direction bit encoding to 0b for symmetric receivers (§ 4.2.18.1.2).
- Kselftest Overhaul:
  * Extended test coverage from 105 to 287 lines, adding comprehensive boundary
    and negative validation tests.
- Link to v1: https://lore.kernel.org/r/20260831-pcie-link-endpoints-v1-1-32c2fd893e9e@google.com
- Link to v7 (monolithic LMR): https://lore.kernel.org/linux-pci/20260828-pcie-lmt-v7-1-6012e9e0940a@google.com/

---
Priyank Rathod (3):
      PCI: Add pcie_get_link_endpoints() helper
      PCI/ASPM: Add pci_aspm_inhibit() helper for temporary link state suppression
      PCI/pcie: Add PCIe Lane Margining at Receiver (LMR) support

 Documentation/PCI/index.rst                  |    1 +
 Documentation/PCI/pcie-lmr.rst               |  174 +++
 MAINTAINERS                                  |    8 +
 drivers/pci/pci.c                            |  152 +++
 drivers/pci/pci.h                            |    8 +
 drivers/pci/pcie/Kconfig                     |   12 +
 drivers/pci/pcie/Makefile                    |    1 +
 drivers/pci/pcie/aspm.c                      |  100 ++
 drivers/pci/pcie/margin.c                    | 1592 ++++++++++++++++++++++++++
 drivers/pci/probe.c                          |    1 +
 drivers/pci/remove.c                         |    2 +-
 include/linux/pci.h                          |   17 +
 include/uapi/linux/pci_regs.h                |   18 +
 tools/testing/selftests/Makefile             |    1 +
 tools/testing/selftests/pcie_lmt/Makefile    |    3 +
 tools/testing/selftests/pcie_lmt/pcie_lmt.sh |  287 +++++
 16 files changed, 2376 insertions(+), 1 deletion(-)
---
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
change-id: 20260831-pcie-link-endpoints-978e100d5d06

Best regards,
-- 
Priyank Rathod <rathodpriyank@google.com>


             reply	other threads:[~2026-09-04  2:48 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-04  2:48 Priyank Rathod [this message]
2026-09-04  2:48 ` [PATCH v2 1/3] PCI: Add pcie_get_link_endpoints() helper Priyank Rathod
2026-09-04  2:48 ` [PATCH v2 2/3] PCI/ASPM: Add pci_aspm_inhibit() helper for temporary link state suppression Priyank Rathod
2026-09-04  2:48 ` [PATCH v2 3/3] PCI/pcie: Add PCIe Lane Margining at Receiver (LMR) support Priyank Rathod

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260904-pcie-link-endpoints-v2-0-16fcb301a3e4@google.com \
    --to=rathodpriyank@google.com \
    --cc=bhelgaas@google.com \
    --cc=corbet@lwn.net \
    --cc=gustavoars@kernel.org \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=kees@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=rdunlap@infradead.org \
    --cc=sashiko-bot@kernel.org \
    --cc=skhan@linuxfoundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox