[PATCH v3 02/16] PCI: dwc: Use cached PCIe capability offset in core
Hans Zhang <[email protected]> Mon, 20 Jul 2026 23:06:05 +0800
| Newsgroups | dev.linux.lists.sophgo,dev.linux.lists.imx,dev.linux.lists.spacemit,org.infradead.lists.linux-amlogic,org.infradead.lists.linux-riscv,org.infradead.lists.linux-rockchip,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci,org.kernel.vger.linux-tegra,org.ozlabs.lists.linuxppc-dev |
|---|---|
| Message-ID | <[email protected]> |
Modify the DWC core functions to use the cached pcie_cap offset instead of calling dw_pcie_find_capability() each time. In the DWC core, dw_pcie_find_capability() is called at several locations: - dw_pcie_ep_init_non_sticky_registers() - dw_pcie_wait_for_link() - dw_pcie_link_set_max_speed() - dw_pcie_link_get_max_link_width() - dw_pcie_link_set_max_link_width() The cached offset is initialized after hardware is ready: - In host mode: dw_pcie_host_init() calls pp->ops->host_init() (enables clocks/resets), then dw_pcie_get_pcie_cap() caches the offset. - In endpoint mode: the core no longer caches automatically. Instead, drivers must call dw_pcie_get_pcie_cap() after hardware is enabled (e.g., after PERST# deassert). dw_pcie_ep_init_non_sticky_registers() is called after that point, so it can safely use pci->pcie_cap. dw_pcie_ep_init_non_sticky_registers() now assumes pci->pcie_cap is valid. if not, it prints a warning and skips the operation. The other functions run after probe, so pci->pcie_cap is already valid and can be used directly. Signed-off-by: Hans Zhang <[email protected]> --- drivers/pci/controller/dwc/pcie-designware-ep.c | 2 +- drivers/pci/controller/dwc/pcie-designware-host.c | 2 ++ drivers/pci/controller/dwc/pcie-designware.c | 15 ++++++--------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 7d2794945704..14228be8bbce 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -1246,7 +1246,7 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci) * to all other functions as well. */ if (funcs > 1) { - offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + offset = pci->pcie_cap; func0_lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); func0_lnkcap = FIELD_GET(PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS, func0_lnkcap); diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 06722259d2e3..fee800ac56d4 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -593,6 +593,8 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp) goto err_free_ecam; } + dw_pcie_get_pcie_cap(pci); + if (pci_msi_enabled()) { pp->use_imsi_rx = !(pp->ops->msi_init || of_property_present(np, "msi-parent") || diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index ec4722ed9303..810729b91892 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -766,7 +766,7 @@ const char *dw_pcie_ltssm_status_string(enum dw_pcie_ltssm ltssm) */ int dw_pcie_wait_for_link(struct dw_pcie *pci) { - u32 offset, val, ltssm; + u32 val, ltssm; int retries; /* Check if the link is up or not */ @@ -806,8 +806,7 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci) pci_host_common_link_train_delay(pci->max_link_speed); - offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); - val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA); + val = dw_pcie_readw_dbi(pci, pci->pcie_cap + PCI_EXP_LNKSTA); dev_info(pci->dev, "PCIe Gen.%u x%u link up\n", FIELD_GET(PCI_EXP_LNKSTA_CLS, val), @@ -843,7 +842,7 @@ EXPORT_SYMBOL_GPL(dw_pcie_upconfig_setup); static void dw_pcie_link_set_max_speed(struct dw_pcie *pci) { u32 cap, ctrl2, link_speed; - u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + u8 offset = pci->pcie_cap; cap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); @@ -890,7 +889,7 @@ static void dw_pcie_link_set_max_speed(struct dw_pcie *pci) int dw_pcie_link_get_max_link_width(struct dw_pcie *pci) { u8 cap = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); - u32 lnkcap = dw_pcie_readl_dbi(pci, cap + PCI_EXP_LNKCAP); + u32 lnkcap = dw_pcie_readl_dbi(pci, pci->pcie_cap + PCI_EXP_LNKCAP); return FIELD_GET(PCI_EXP_LNKCAP_MLW, lnkcap); } @@ -898,7 +897,6 @@ int dw_pcie_link_get_max_link_width(struct dw_pcie *pci) static void dw_pcie_link_set_max_link_width(struct dw_pcie *pci, u32 num_lanes) { u32 lnkcap, lwsc, plc; - u8 cap; if (!num_lanes) return; @@ -935,10 +933,9 @@ static void dw_pcie_link_set_max_link_width(struct dw_pcie *pci, u32 num_lanes) dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, plc); dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, lwsc); - cap = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); - lnkcap = dw_pcie_readl_dbi(pci, cap + PCI_EXP_LNKCAP); + lnkcap = dw_pcie_readl_dbi(pci, pci->pcie_cap + PCI_EXP_LNKCAP); FIELD_MODIFY(PCI_EXP_LNKCAP_MLW, &lnkcap, num_lanes); - dw_pcie_writel_dbi(pci, cap + PCI_EXP_LNKCAP, lnkcap); + dw_pcie_writel_dbi(pci, pci->pcie_cap + PCI_EXP_LNKCAP, lnkcap); } void dw_pcie_iatu_detect(struct dw_pcie *pci) -- 2.34.1