[PATCH v2 00/16] PCI: dwc: Cache PCIe capability offset and simplify drivers
From: Hans Zhang
Date: Sat May 30 2026 - 11:36:23 EST
Hi,
The DWC PCIe core and its many platform drivers repeatedly call
dw_pcie_find_capability(pci, PCI_CAP_ID_EXP) to obtain the offset of the
PCI Express Capability structure. This is wasteful and makes the code
verbose. Some drivers even search for the offset in suspend/resume paths.
Add a cached pcie_cap field in struct dw_pcie and a helper
dw_pcie_get_pcie_cap() to initialize it once at the point when the
hardware is ready. Then replace all explicit capability searches with
the cached value across the entire dwc subtree.
**Safety analysis: DBI access timing**
The PCIe Capability offset is read from DBI configuration space. DBI
registers are only accessible after the controller's clocks, resets, and
power are enabled. The following call graph demonstrates that all
dw_pcie_find_capability() replacements occur only after hardware is ready:
- For Root Complex mode:
dw_pcie_host_init()
...
if (pp->ops->init)
pp->ops->init [enables clocks/resets]
dw_pcie_get_pcie_cap() [caches offset]
...
dw_pcie_link_up
pci->ops->link_up
...
dw_pcie_start_link
pci->ops->start_link
...
pci_host_probe
if (pp->ops->post_init)
pp->ops->post_init
...
- For Endpoint mode:
dw_pcie_ep_init()
ep->ops->pre_init() [enables clocks/resets]
dw_pcie_get_pcie_cap() [caches offset]
dw_pcie_ep_init_non_sticky_registers() etc.
- Some platform drivers (e.g., layerscape-ep, tegra194) need the offset
before calling dw_pcie_ep_init() / dw_pcie_host_init(). They already
enable hardware themselves and explicitly call dw_pcie_get_pcie_cap()
before the core caches it. This is safe and ensures the cached value is
available for all later users.
Thus, no DBI access occurs before hardware is operational.
Changes in v2:
- Move dw_pcie_get_pcie_cap() from the beginning of dw_pcie_host_init()
and dw_pcie_ep_init() to after the hardware initialization callbacks
(host_init/pre_init). This can prevent the reading of DBI when the clock
is turned off or when the hardware is not ready.
- Convert all platform drivers to use the cached offset via
dw_pcie_get_pcie_cap() or directly pci->pcie_cap where safe.
- Fix type mismatches (u16 -> u8).
- Properly split per-driver modifications.
v1:
https://patchwork.kernel.org/project/linux-pci/cover/20260509135152.2241235-1-18255117159@xxxxxxx/
---
**Why splitting into per-driver patches**
To facilitate review and potential bisection, each platform driver is
modified in its own patch. The core changes are in patches 1-2, and
follow-up patches convert individual glue drivers. If maintainers prefer
to squash them, please let me know and I will merge in v3.
This splitting patch of each controller was carried out solely for
the convenience of code review.
---
Hans Zhang (16):
PCI: dwc: Add pcie_cap field and helper in designware header
PCI: dwc: Use cached PCIe capability offset in core
PCI: dwc: imx6: Use cached PCIe capability offset
PCI: dwc: layerscape-ep: Use cached PCIe capability offset
PCI: dwc: meson: Use cached PCIe capability offset
PCI: dwc: rockchip: Use cached PCIe capability offset
PCI: dwc: eswin: Use cached PCIe capability offset
PCI: dwc: fu740: Use cached PCIe capability offset
PCI: dwc: intel-gw: Use cached PCIe capability offset
PCI: dwc: qcom-ep: Use cached PCIe capability offset
PCI: dwc: qcom: Use cached PCIe capability offset
PCI: dwc: sophgo: Use cached PCIe capability offset
PCI: dwc: spacemit-k1: Use cached PCIe capability offset
PCI: dwc: spear13xx: Use cached PCIe capability offset
PCI: dwc: tegra194: Use cached PCIe capability offset
PCI: dwc: ultrarisc: Use cached PCIe capability offset
drivers/pci/controller/dwc/pci-imx6.c | 6 +++---
.../pci/controller/dwc/pci-layerscape-ep.c | 9 +++-----
drivers/pci/controller/dwc/pci-meson.c | 4 ++--
.../pci/controller/dwc/pcie-designware-ep.c | 4 +++-
.../pci/controller/dwc/pcie-designware-host.c | 2 ++
drivers/pci/controller/dwc/pcie-designware.c | 16 ++++++--------
drivers/pci/controller/dwc/pcie-designware.h | 17 +++++++++++++++
drivers/pci/controller/dwc/pcie-dw-rockchip.c | 2 +-
drivers/pci/controller/dwc/pcie-eswin.c | 3 +--
drivers/pci/controller/dwc/pcie-fu740.c | 2 +-
drivers/pci/controller/dwc/pcie-intel-gw.c | 2 +-
drivers/pci/controller/dwc/pcie-qcom-ep.c | 11 ++++------
drivers/pci/controller/dwc/pcie-qcom.c | 21 ++++++++-----------
drivers/pci/controller/dwc/pcie-sophgo.c | 5 +++--
drivers/pci/controller/dwc/pcie-spacemit-k1.c | 2 +-
drivers/pci/controller/dwc/pcie-spear13xx.c | 2 +-
drivers/pci/controller/dwc/pcie-tegra194.c | 6 ++----
drivers/pci/controller/dwc/pcie-ultrarisc.c | 2 +-
18 files changed, 61 insertions(+), 55 deletions(-)
base-commit: 3a97877d13e1a29c50ab15ed0a0aba87b75061dd
--
2.34.1