mirror of https://lore.kernel.org/linux-amlogic/
 help / color / mirror / Atom feed
* [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers
@ 2026-05-09 13:51 Hans Zhang
  2026-05-09 13:51 ` [PATCH 1/3] PCI: dwc: Add pcie_cap field and helper in designware header Hans Zhang
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Hans Zhang @ 2026-05-09 13:51 UTC (permalink / raw)
  To: bhelgaas, lpieralisi, kwilczynski, mani, jingoohan1
  Cc: mx, linuxppc-dev, linux-amlogic, linux-rockchip, linux-arm-msm,
	sophgo, linux-riscv, spacemit, linux-tegra, linux-pci,
	linux-kernel, Hans Zhang

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. And some even search for the PCI_CAP_ID_EXP offset value within
the suspend/resume functions.

Add a cached pcie_cap field in struct dw_pcie and a helper
dw_pcie_get_pcie_cap() to initialize it once at probe time. Then replace
all explicit capability searches with the cached value across the
entire dwc subtree.

Hans Zhang (3):
  PCI: dwc: Add pcie_cap field and helper in designware header
  PCI: dwc: Use cached PCIe capability offset in core
  PCI: dwc: Simplify platform drivers using cached capability offset

 drivers/pci/controller/dwc/pci-imx6.c         |  6 +--
 .../pci/controller/dwc/pci-layerscape-ep.c    |  4 +-
 drivers/pci/controller/dwc/pci-meson.c        |  4 +-
 .../pci/controller/dwc/pcie-designware-ep.c   |  4 +-
 .../pci/controller/dwc/pcie-designware-host.c |  4 +-
 drivers/pci/controller/dwc/pcie-designware.c  | 16 +++---
 drivers/pci/controller/dwc/pcie-designware.h  | 17 +++++++
 drivers/pci/controller/dwc/pcie-dw-rockchip.c | 15 +++---
 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        | 24 ++++-----
 drivers/pci/controller/dwc/pcie-sophgo.c      |  8 ++-
 drivers/pci/controller/dwc/pcie-spacemit-k1.c |  5 +-
 drivers/pci/controller/dwc/pcie-spear13xx.c   |  6 +--
 drivers/pci/controller/dwc/pcie-tegra194.c    | 51 +++++++------------
 17 files changed, 85 insertions(+), 97 deletions(-)


base-commit: 70390501d1944d4e5b8f7352be180fceb3a44132
-- 
2.34.1


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] PCI: dwc: Add pcie_cap field and helper in designware header
  2026-05-09 13:51 [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers Hans Zhang
@ 2026-05-09 13:51 ` Hans Zhang
  2026-05-09 13:51 ` [PATCH 2/3] PCI: dwc: Use cached PCIe capability offset in core Hans Zhang
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Hans Zhang @ 2026-05-09 13:51 UTC (permalink / raw)
  To: bhelgaas, lpieralisi, kwilczynski, mani, jingoohan1
  Cc: mx, linuxppc-dev, linux-amlogic, linux-rockchip, linux-arm-msm,
	sophgo, linux-riscv, spacemit, linux-tegra, linux-pci,
	linux-kernel, Hans Zhang

Add a pcie_cap field to struct dw_pcie to store the offset of the
PCI Express Capability structure. Provide a helper dw_pcie_get_pcie_cap()
which performs the capability search on first call and caches the result.

This is a preparatory step for replacing repetitive capability searches
in both core and platform drivers.

Signed-off-by: Hans Zhang <18255117159@163.com>
---
 drivers/pci/controller/dwc/pcie-designware.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 3e69ef60165b..4baf7eb072eb 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -568,6 +568,8 @@ struct dw_pcie {
 	 * use_parent_dt_ranges to true to avoid this warning.
 	 */
 	bool			use_parent_dt_ranges;
+
+	u8			pcie_cap;	/* PCIe capability offset */
 };
 
 #define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp)
@@ -805,6 +807,21 @@ static inline void dw_pcie_dbi_ro_wr_dis(struct dw_pcie *pci)
 	dw_pcie_writel_dbi(pci, reg, val);
 }
 
+/**
+ * dw_pcie_get_pcie_cap() - Return cached PCIe Capability offset
+ * @pci: DWC instance
+ *
+ * Finds and caches the offset of PCI_CAP_ID_EXP on first call.
+ * Returns 0 if the capability is not present.
+ */
+static inline u8 dw_pcie_get_pcie_cap(struct dw_pcie *pci)
+{
+	if (!pci->pcie_cap)
+		pci->pcie_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+
+	return pci->pcie_cap;
+}
+
 static inline int dw_pcie_start_link(struct dw_pcie *pci)
 {
 	if (pci->ops && pci->ops->start_link)
-- 
2.34.1


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/3] PCI: dwc: Use cached PCIe capability offset in core
  2026-05-09 13:51 [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers Hans Zhang
  2026-05-09 13:51 ` [PATCH 1/3] PCI: dwc: Add pcie_cap field and helper in designware header Hans Zhang
@ 2026-05-09 13:51 ` Hans Zhang
  2026-05-09 13:51 ` [PATCH 3/3] PCI: dwc: Simplify platform drivers using cached capability offset Hans Zhang
  2026-05-19 13:57 ` [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers Manivannan Sadhasivam
  3 siblings, 0 replies; 10+ messages in thread
From: Hans Zhang @ 2026-05-09 13:51 UTC (permalink / raw)
  To: bhelgaas, lpieralisi, kwilczynski, mani, jingoohan1
  Cc: mx, linuxppc-dev, linux-amlogic, linux-rockchip, linux-arm-msm,
	sophgo, linux-riscv, spacemit, linux-tegra, linux-pci,
	linux-kernel, Hans Zhang

Modify the DWC core functions to use the cached pcie_cap offset instead
of calling dw_pcie_find_capability() each time.

Signed-off-by: Hans Zhang <18255117159@163.com>
---
 drivers/pci/controller/dwc/pcie-designware-ep.c  |  4 +++-
 .../pci/controller/dwc/pcie-designware-host.c    |  4 +++-
 drivers/pci/controller/dwc/pcie-designware.c     | 16 ++++++----------
 3 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index d4dc3b24da60..fdcb9012058d 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -1128,7 +1128,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 = dw_pcie_get_pcie_cap(pci);
 		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);
@@ -1390,6 +1390,8 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 	ep->msi_msg_addr = 0;
 	ep->msi_map_size = 0;
 
+	dw_pcie_get_pcie_cap(pci);
+
 	epc = devm_pci_epc_create(dev, &epc_ops);
 	if (IS_ERR(epc)) {
 		dev_err(dev, "Failed to create epc device\n");
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index c9517a348836..7b3ba83ed616 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -575,6 +575,8 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 
 	raw_spin_lock_init(&pp->lock);
 
+	dw_pcie_get_pcie_cap(pci);
+
 	bridge = devm_pci_alloc_host_bridge(dev, 0);
 	if (!bridge)
 		return -ENOMEM;
@@ -1218,7 +1220,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
 
 int dw_pcie_suspend_noirq(struct dw_pcie *pci)
 {
-	u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+	u8 offset = pci->pcie_cap;
 	int ret = 0;
 	u32 val;
 
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index c11cf61b8319..db62b93c6255 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -761,7 +761,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 */
@@ -807,8 +807,7 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci)
 	if (pci->max_link_speed > 2)
 		msleep(PCIE_RESET_CONFIG_WAIT_MS);
 
-	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),
@@ -844,7 +843,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,8 +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);
 }
@@ -899,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;
@@ -936,11 +933,10 @@ 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);
 	lnkcap &= ~PCI_EXP_LNKCAP_MLW;
 	lnkcap |= FIELD_PREP(PCI_EXP_LNKCAP_MLW, 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


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 3/3] PCI: dwc: Simplify platform drivers using cached capability offset
  2026-05-09 13:51 [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers Hans Zhang
  2026-05-09 13:51 ` [PATCH 1/3] PCI: dwc: Add pcie_cap field and helper in designware header Hans Zhang
  2026-05-09 13:51 ` [PATCH 2/3] PCI: dwc: Use cached PCIe capability offset in core Hans Zhang
@ 2026-05-09 13:51 ` Hans Zhang
  2026-05-19 13:57 ` [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers Manivannan Sadhasivam
  3 siblings, 0 replies; 10+ messages in thread
From: Hans Zhang @ 2026-05-09 13:51 UTC (permalink / raw)
  To: bhelgaas, lpieralisi, kwilczynski, mani, jingoohan1
  Cc: mx, linuxppc-dev, linux-amlogic, linux-rockchip, linux-arm-msm,
	sophgo, linux-riscv, spacemit, linux-tegra, linux-pci,
	linux-kernel, Hans Zhang

Replace explicit dw_pcie_find_capability(pci, PCI_CAP_ID_EXP) calls
with the cached pci->pcie_cap in all DWC-based platform drivers:

- i.MX6, Layerscape EP, Meson
- Rockchip (also remove redundant NULL check and fix typo)
- Eswin, Fu740
- Intel Gateway, Qualcomm EP, Qualcomm RC
- Sophgo, Spacemit-k1, Spear13xx
- Tegra194 (remove private pcie_cap_base)

For drivers that need the offset before the core caches it (e.g.,
ls_pcie_ep_probe), use dw_pcie_get_pcie_cap() to ensure caching.

Adjust variable types from u16 to u8 where appropriate.

Signed-off-by: Hans Zhang <18255117159@163.com>
---
 drivers/pci/controller/dwc/pci-imx6.c         |  6 +--
 .../pci/controller/dwc/pci-layerscape-ep.c    |  4 +-
 drivers/pci/controller/dwc/pci-meson.c        |  4 +-
 drivers/pci/controller/dwc/pcie-dw-rockchip.c | 15 +++---
 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        | 24 ++++-----
 drivers/pci/controller/dwc/pcie-sophgo.c      |  8 ++-
 drivers/pci/controller/dwc/pcie-spacemit-k1.c |  5 +-
 drivers/pci/controller/dwc/pcie-spear13xx.c   |  6 +--
 drivers/pci/controller/dwc/pcie-tegra194.c    | 51 +++++++------------
 13 files changed, 56 insertions(+), 85 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index e35044cc5218..dc464b460fc1 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -936,10 +936,10 @@ static void imx_pcie_ltssm_enable(struct device *dev)
 {
 	struct imx_pcie *imx_pcie = dev_get_drvdata(dev);
 	const struct imx_pcie_drvdata *drvdata = imx_pcie->drvdata;
-	u8 offset = dw_pcie_find_capability(imx_pcie->pci, PCI_CAP_ID_EXP);
+	struct dw_pcie *pci = imx_pcie->pci;
 	u32 tmp;
 
-	tmp = dw_pcie_readl_dbi(imx_pcie->pci, offset + PCI_EXP_LNKCAP);
+	tmp = dw_pcie_readl_dbi(pci, pci->pcie_cap + PCI_EXP_LNKCAP);
 	phy_set_speed(imx_pcie->phy, FIELD_GET(PCI_EXP_LNKCAP_SLS, tmp));
 	if (drvdata->ltssm_mask)
 		regmap_update_bits(imx_pcie->iomuxc_gpr, drvdata->ltssm_off, drvdata->ltssm_mask,
@@ -965,7 +965,7 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
 {
 	struct imx_pcie *imx_pcie = to_imx_pcie(pci);
 	struct device *dev = pci->dev;
-	u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+	u8 offset = pci->pcie_cap;
 	u32 tmp;
 	int ret;
 
diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 8936975ff104..fdb89ae13e4a 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -84,7 +84,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void *dev_id)
 
 	if (val & PEX_PF0_PME_MES_DR_LUD) {
 
-		offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+		offset = dw_pcie_get_pcie_cap(pci);
 
 		/*
 		 * The values of the Maximum Link Width and Supported Link
@@ -266,7 +266,7 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, pcie);
 
-	offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+	offset = dw_pcie_get_pcie_cap(pci);
 	pcie->lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
 
 	ret = dw_pcie_ep_init(&pci->ep);
diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
index 0694084f612b..e8750178fbb0 100644
--- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -276,7 +276,7 @@ static void meson_set_max_payload(struct meson_pcie *mp, int size)
 {
 	struct dw_pcie *pci = &mp->pci;
 	u32 val;
-	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+	u8 offset = pci->pcie_cap;
 	int max_payload_size = meson_size_to_payload(mp, size);
 
 	val = dw_pcie_readl_dbi(pci, offset + PCI_EXP_DEVCTL);
@@ -292,7 +292,7 @@ static void meson_set_max_rd_req_size(struct meson_pcie *mp, int size)
 {
 	struct dw_pcie *pci = &mp->pci;
 	u32 val;
-	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+	u8 offset = pci->pcie_cap;
 	int max_rd_req_size = meson_size_to_payload(mp, size);
 
 	val = dw_pcie_readl_dbi(pci, offset + PCI_EXP_DEVCTL);
diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index 731d93663cca..9acdc18a573e 100644
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -366,17 +366,14 @@ static void rockchip_pcie_configure_l1ss(struct dw_pcie *pci)
 
 static void rockchip_pcie_enable_l0s(struct dw_pcie *pci)
 {
-	u32 cap, lnkcap;
+	u32 lnkcap;
 
 	/* Enable L0S capability for all SoCs */
-	cap = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
-	if (cap) {
-		lnkcap = dw_pcie_readl_dbi(pci, cap + PCI_EXP_LNKCAP);
-		lnkcap |= PCI_EXP_LNKCAP_ASPM_L0S;
-		dw_pcie_dbi_ro_wr_en(pci);
-		dw_pcie_writel_dbi(pci, cap + PCI_EXP_LNKCAP, lnkcap);
-		dw_pcie_dbi_ro_wr_dis(pci);
-	}
+	lnkcap = dw_pcie_readl_dbi(pci, pci->pcie_cap + PCI_EXP_LNKCAP);
+	lnkcap |= PCI_EXP_LNKCAP_ASPM_L0S;
+	dw_pcie_dbi_ro_wr_en(pci);
+	dw_pcie_writel_dbi(pci, pci->pcie_cap + PCI_EXP_LNKCAP, lnkcap);
+	dw_pcie_dbi_ro_wr_dis(pci);
 }
 
 static int rockchip_pcie_start_link(struct dw_pcie *pci)
diff --git a/drivers/pci/controller/dwc/pcie-eswin.c b/drivers/pci/controller/dwc/pcie-eswin.c
index 2845832b3824..2e5b94c27026 100644
--- a/drivers/pci/controller/dwc/pcie-eswin.c
+++ b/drivers/pci/controller/dwc/pcie-eswin.c
@@ -84,8 +84,7 @@ static int eswin_pcie_start_link(struct dw_pcie *pci)
 
 static bool eswin_pcie_link_up(struct dw_pcie *pci)
 {
-	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
-	u16 val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
+	u16 val = dw_pcie_readw_dbi(pci, pci->pcie_cap + PCI_EXP_LNKSTA);
 
 	return val & PCI_EXP_LNKSTA_DLLLA;
 }
diff --git a/drivers/pci/controller/dwc/pcie-fu740.c b/drivers/pci/controller/dwc/pcie-fu740.c
index 66367252032b..553a940e6d89 100644
--- a/drivers/pci/controller/dwc/pcie-fu740.c
+++ b/drivers/pci/controller/dwc/pcie-fu740.c
@@ -179,7 +179,7 @@ static int fu740_pcie_start_link(struct dw_pcie *pci)
 {
 	struct device *dev = pci->dev;
 	struct fu740_pcie *afp = dev_get_drvdata(dev);
-	u8 cap_exp = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+	u8 cap_exp = pci->pcie_cap;
 	int ret;
 	u32 orig, tmp;
 
diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c
index c21906eced61..939b9dcac7fe 100644
--- a/drivers/pci/controller/dwc/pcie-intel-gw.c
+++ b/drivers/pci/controller/dwc/pcie-intel-gw.c
@@ -121,7 +121,7 @@ static void intel_pcie_ltssm_disable(struct intel_pcie *pcie)
 static void intel_pcie_link_setup(struct intel_pcie *pcie)
 {
 	u32 val;
-	u8 offset = dw_pcie_find_capability(&pcie->pci, PCI_CAP_ID_EXP);
+	u8 offset = pcie->pci.pcie_cap;
 
 	val = pcie_rc_cfg_rd(pcie, offset + PCI_EXP_LNKCTL);
 
diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c
index 257c2bcb5f76..d041189be248 100644
--- a/drivers/pci/controller/dwc/pcie-qcom-ep.c
+++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c
@@ -307,14 +307,14 @@ static void qcom_pcie_dw_write_dbi2(struct dw_pcie *pci, void __iomem *base,
 static void qcom_pcie_ep_icc_update(struct qcom_pcie_ep *pcie_ep)
 {
 	struct dw_pcie *pci = &pcie_ep->pci;
-	u32 offset, status;
-	int speed, width;
-	int ret;
+	int speed, width, ret;
+	u32 status;
+	u8 offset;
 
 	if (!pcie_ep->icc_mem)
 		return;
 
-	offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+	offset = dw_pcie_get_pcie_cap(pci);
 	status = readw(pci->dbi_base + offset + PCI_EXP_LNKSTA);
 
 	speed = FIELD_GET(PCI_EXP_LNKSTA_CLS, status);
@@ -492,14 +492,13 @@ static int qcom_pcie_perst_deassert(struct dw_pcie *pci)
 	dw_pcie_dbi_ro_wr_en(pci);
 
 	/* Set the L0s Exit Latency to 2us-4us = 0x6 */
-	offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+	offset = dw_pcie_get_pcie_cap(pci);
 	val = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
 	val &= ~PCI_EXP_LNKCAP_L0SEL;
 	val |= FIELD_PREP(PCI_EXP_LNKCAP_L0SEL, 0x6);
 	dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, val);
 
 	/* Set the L1 Exit Latency to be 32us-64 us = 0x6 */
-	offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
 	val = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
 	val &= ~PCI_EXP_LNKCAP_L1EL;
 	val |= FIELD_PREP(PCI_EXP_LNKCAP_L1EL, 0x6);
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index af6bf5cce65b..ddb0ae2bf64b 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -333,26 +333,22 @@ static int qcom_pcie_start_link(struct dw_pcie *pci)
 static void qcom_pcie_clear_aspm_l0s(struct dw_pcie *pci)
 {
 	struct qcom_pcie *pcie = to_qcom_pcie(pci);
-	u16 offset;
 	u32 val;
 
 	if (!pcie->cfg->no_l0s)
 		return;
 
-	offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
-
 	dw_pcie_dbi_ro_wr_en(pci);
 
-	val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP);
+	val = readl(pci->dbi_base + pci->pcie_cap + PCI_EXP_LNKCAP);
 	val &= ~PCI_EXP_LNKCAP_ASPM_L0S;
-	writel(val, pci->dbi_base + offset + PCI_EXP_LNKCAP);
+	writel(val, pci->dbi_base + pci->pcie_cap + PCI_EXP_LNKCAP);
 
 	dw_pcie_dbi_ro_wr_dis(pci);
 }
 
 static void qcom_pcie_set_slot_nccs(struct dw_pcie *pci)
 {
-	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
 	u32 val;
 
 	dw_pcie_dbi_ro_wr_en(pci);
@@ -362,9 +358,9 @@ static void qcom_pcie_set_slot_nccs(struct dw_pcie *pci)
 	 * notifications for the Hot-Plug commands. So set the NCCS field to
 	 * avoid waiting for the completions.
 	 */
-	val = readl(pci->dbi_base + offset + PCI_EXP_SLTCAP);
+	val = readl(pci->dbi_base + pci->pcie_cap + PCI_EXP_SLTCAP);
 	val |= PCI_EXP_SLTCAP_NCCS;
-	writel(val, pci->dbi_base + offset + PCI_EXP_SLTCAP);
+	writel(val, pci->dbi_base + pci->pcie_cap + PCI_EXP_SLTCAP);
 
 	dw_pcie_dbi_ro_wr_dis(pci);
 }
@@ -900,7 +896,7 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie)
 static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie)
 {
 	struct dw_pcie *pci = pcie->pci;
-	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+	u8 offset = pci->pcie_cap;
 	u32 val;
 
 	val = readl(pcie->parf + PARF_PHY_CTRL);
@@ -1209,7 +1205,7 @@ static int qcom_pcie_init_2_9_0(struct qcom_pcie *pcie)
 static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie)
 {
 	struct dw_pcie *pci = pcie->pci;
-	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+	u8 offset = pci->pcie_cap;
 	u32 val;
 	int i;
 
@@ -1254,8 +1250,7 @@ static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie)
 
 static bool qcom_pcie_link_up(struct dw_pcie *pci)
 {
-	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
-	u16 val = readw(pci->dbi_base + offset + PCI_EXP_LNKSTA);
+	u16 val = readw(pci->dbi_base + pci->pcie_cap + PCI_EXP_LNKSTA);
 
 	return val & PCI_EXP_LNKSTA_DLLLA;
 }
@@ -1559,15 +1554,14 @@ static int qcom_pcie_icc_init(struct qcom_pcie *pcie)
 
 static void qcom_pcie_icc_opp_update(struct qcom_pcie *pcie)
 {
-	u32 offset, status, width, speed;
+	u32 status, width, speed;
 	struct dw_pcie *pci = pcie->pci;
 	struct dev_pm_opp_key key = {};
 	unsigned long freq_kbps;
 	struct dev_pm_opp *opp;
 	int ret, freq_mbps;
 
-	offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
-	status = readw(pci->dbi_base + offset + PCI_EXP_LNKSTA);
+	status = readw(pci->dbi_base + pci->pcie_cap + PCI_EXP_LNKSTA);
 
 	/* Only update constraints if link is up. */
 	if (!(status & PCI_EXP_LNKSTA_DLLLA))
diff --git a/drivers/pci/controller/dwc/pcie-sophgo.c b/drivers/pci/controller/dwc/pcie-sophgo.c
index 044088898819..5a2cd95c6de7 100644
--- a/drivers/pci/controller/dwc/pcie-sophgo.c
+++ b/drivers/pci/controller/dwc/pcie-sophgo.c
@@ -164,15 +164,13 @@ static void sophgo_pcie_msi_enable(struct dw_pcie_rp *pp)
 static void sophgo_pcie_disable_l0s_l1(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-	u32 offset, val;
-
-	offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+	u32 val;
 
 	dw_pcie_dbi_ro_wr_en(pci);
 
-	val = dw_pcie_readl_dbi(pci, PCI_EXP_LNKCAP + offset);
+	val = dw_pcie_readl_dbi(pci, PCI_EXP_LNKCAP + pci->pcie_cap);
 	val &= ~(PCI_EXP_LNKCAP_ASPM_L0S | PCI_EXP_LNKCAP_ASPM_L1);
-	dw_pcie_writel_dbi(pci, PCI_EXP_LNKCAP + offset, val);
+	dw_pcie_writel_dbi(pci, PCI_EXP_LNKCAP + pci->pcie_cap, val);
 
 	dw_pcie_dbi_ro_wr_dis(pci);
 }
diff --git a/drivers/pci/controller/dwc/pcie-spacemit-k1.c b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
index be20a520255b..6f0556336f44 100644
--- a/drivers/pci/controller/dwc/pcie-spacemit-k1.c
+++ b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
@@ -114,12 +114,9 @@ static void k1_pcie_disable_resources(struct k1_pcie *k1)
 static void k1_pcie_disable_aspm_l1(struct k1_pcie *k1)
 {
 	struct dw_pcie *pci = &k1->pci;
-	u8 offset;
+	u8 offset = pci->pcie_cap + PCI_EXP_LNKCAP;
 	u32 val;
 
-	offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
-	offset += PCI_EXP_LNKCAP;
-
 	dw_pcie_dbi_ro_wr_en(pci);
 	val = dw_pcie_readl_dbi(pci, offset);
 	val &= ~PCI_EXP_LNKCAP_ASPM_L1;
diff --git a/drivers/pci/controller/dwc/pcie-spear13xx.c b/drivers/pci/controller/dwc/pcie-spear13xx.c
index 01794a9d3ad2..920454266f3f 100644
--- a/drivers/pci/controller/dwc/pcie-spear13xx.c
+++ b/drivers/pci/controller/dwc/pcie-spear13xx.c
@@ -122,7 +122,7 @@ static int spear13xx_pcie_host_init(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 	struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
-	u32 exp_cap_off = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+	u8 offset = pci->pcie_cap;
 	u32 val;
 
 	spear13xx_pcie->app_base = pci->dbi_base + 0x2000;
@@ -132,9 +132,9 @@ static int spear13xx_pcie_host_init(struct dw_pcie_rp *pp)
 	 * default value in capability register is 512 bytes. So force
 	 * it to 128 here.
 	 */
-	val = dw_pcie_readw_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL);
+	val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_DEVCTL);
 	val &= ~PCI_EXP_DEVCTL_READRQ;
-	dw_pcie_writew_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL, val);
+	dw_pcie_writew_dbi(pci, offset + PCI_EXP_DEVCTL, val);
 
 	dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, 0x104A);
 	dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, 0xCD80);
diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 9dcfa194050e..0d5a5e9027d9 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -268,7 +268,6 @@ struct tegra_pcie_dw {
 	u32 num_lanes;
 	u32 cid;
 	u32 ras_des_cap;
-	u32 pcie_cap_base;
 	u32 aspm_cmrt;
 	u32 aspm_pwr_on_t;
 	u32 aspm_l0s_enter_lat;
@@ -312,7 +311,7 @@ static void tegra_pcie_icc_set(struct tegra_pcie_dw *pcie)
 	struct dw_pcie *pci = &pcie->pci;
 	u32 val, speed, width;
 
-	val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA);
+	val = dw_pcie_readw_dbi(pci, pci->pcie_cap + PCI_EXP_LNKSTA);
 
 	speed = FIELD_GET(PCI_EXP_LNKSTA_CLS, val);
 	width = FIELD_GET(PCI_EXP_LNKSTA_NLW, val);
@@ -340,22 +339,22 @@ static void apply_bad_link_workaround(struct dw_pcie_rp *pp)
 	 * stable anyway, not waiting to confirm if link is really
 	 * transitioning to Gen-2 speed
 	 */
-	val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA);
+	val = dw_pcie_readw_dbi(pci, pci->pcie_cap + PCI_EXP_LNKSTA);
 	if (val & PCI_EXP_LNKSTA_LBMS) {
 		current_link_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, val);
 		if (pcie->init_link_width > current_link_width) {
 			dev_warn(pci->dev, "PCIe link is bad, width reduced\n");
-			val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base +
+			val = dw_pcie_readw_dbi(pci, pci->pcie_cap +
 						PCI_EXP_LNKCTL2);
 			val &= ~PCI_EXP_LNKCTL2_TLS;
 			val |= PCI_EXP_LNKCTL2_TLS_2_5GT;
-			dw_pcie_writew_dbi(pci, pcie->pcie_cap_base +
+			dw_pcie_writew_dbi(pci, pci->pcie_cap +
 					   PCI_EXP_LNKCTL2, val);
 
-			val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base +
+			val = dw_pcie_readw_dbi(pci, pci->pcie_cap +
 						PCI_EXP_LNKCTL);
 			val |= PCI_EXP_LNKCTL_RL;
-			dw_pcie_writew_dbi(pci, pcie->pcie_cap_base +
+			dw_pcie_writew_dbi(pci, pci->pcie_cap +
 					   PCI_EXP_LNKCTL, val);
 		}
 	}
@@ -399,17 +398,17 @@ static irqreturn_t tegra_pcie_rp_irq_handler(int irq, void *arg)
 			apply_bad_link_workaround(pp);
 		}
 		if (status_l1 & APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS) {
-			val_w = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base +
+			val_w = dw_pcie_readw_dbi(pci, pci->pcie_cap +
 						  PCI_EXP_LNKSTA);
 			val_w |= PCI_EXP_LNKSTA_LBMS;
-			dw_pcie_writew_dbi(pci, pcie->pcie_cap_base +
+			dw_pcie_writew_dbi(pci, pci->pcie_cap +
 					   PCI_EXP_LNKSTA, val_w);
 
 			appl_writel(pcie,
 				    APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS,
 				    APPL_INTR_STATUS_L1_8_0);
 
-			val_w = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base +
+			val_w = dw_pcie_readw_dbi(pci, pci->pcie_cap +
 						  PCI_EXP_LNKSTA);
 			dev_dbg(pci->dev, "Link Speed : Gen-%u\n", val_w &
 				PCI_EXP_LNKSTA_CLS);
@@ -675,7 +674,7 @@ static void init_host_aspm(struct tegra_pcie_dw *pcie)
 
 	l1ss = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_L1SS);
 
-	pcie->ras_des_cap = dw_pcie_find_ext_capability(&pcie->pci,
+	pcie->ras_des_cap = dw_pcie_find_ext_capability(pci,
 							PCI_EXT_CAP_ID_VNDR);
 
 	/* Enable ASPM counters */
@@ -766,15 +765,12 @@ static void tegra_pcie_enable_system_interrupts(struct dw_pcie_rp *pp)
 		appl_writel(pcie, val, APPL_INTR_EN_L1_18);
 	}
 
-	val_w = dw_pcie_readw_dbi(&pcie->pci, pcie->pcie_cap_base +
-				  PCI_EXP_LNKSTA);
+	val_w = dw_pcie_readw_dbi(pci, pci->pcie_cap + PCI_EXP_LNKSTA);
 	pcie->init_link_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, val_w);
 
-	val_w = dw_pcie_readw_dbi(&pcie->pci, pcie->pcie_cap_base +
-				  PCI_EXP_LNKCTL);
+	val_w = dw_pcie_readw_dbi(pci, pci->pcie_cap + PCI_EXP_LNKCTL);
 	val_w |= PCI_EXP_LNKCTL_LBMIE;
-	dw_pcie_writew_dbi(&pcie->pci, pcie->pcie_cap_base + PCI_EXP_LNKCTL,
-			   val_w);
+	dw_pcie_writew_dbi(pci, pci->pcie_cap + PCI_EXP_LNKCTL, val_w);
 }
 
 static void tegra_pcie_enable_intx_interrupts(struct dw_pcie_rp *pp)
@@ -903,10 +899,6 @@ static int tegra_pcie_dw_host_init(struct dw_pcie_rp *pp)
 
 	pp->bridge->ops = &tegra_pci_ops;
 
-	if (!pcie->pcie_cap_base)
-		pcie->pcie_cap_base = dw_pcie_find_capability(&pcie->pci,
-							      PCI_CAP_ID_EXP);
-
 	val = dw_pcie_readl_dbi(pci, PCI_IO_BASE);
 	val &= ~(IO_BASE_IO_DECODE | IO_BASE_IO_DECODE_BIT8);
 	dw_pcie_writel_dbi(pci, PCI_IO_BASE, val);
@@ -927,10 +919,9 @@ static int tegra_pcie_dw_host_init(struct dw_pcie_rp *pp)
 
 	/* Clear Slot Clock Configuration bit if SRNS configuration */
 	if (pcie->enable_srns) {
-		val_16 = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base +
-					   PCI_EXP_LNKSTA);
+		val_16 = dw_pcie_readw_dbi(pci, pci->pcie_cap + PCI_EXP_LNKSTA);
 		val_16 &= ~PCI_EXP_LNKSTA_SLC;
-		dw_pcie_writew_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA,
+		dw_pcie_writew_dbi(pci, pci->pcie_cap + PCI_EXP_LNKSTA,
 				   val_16);
 	}
 
@@ -1047,8 +1038,7 @@ static int tegra_pcie_dw_start_link(struct dw_pcie *pci)
 
 static bool tegra_pcie_dw_link_up(struct dw_pcie *pci)
 {
-	struct tegra_pcie_dw *pcie = to_tegra_pcie(pci);
-	u32 val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA);
+	u32 val = dw_pcie_readw_dbi(pci, pci->pcie_cap + PCI_EXP_LNKSTA);
 
 	return val & PCI_EXP_LNKSTA_DLLLA;
 }
@@ -1878,16 +1868,13 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
 		dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val);
 	}
 
-	pcie->pcie_cap_base = dw_pcie_find_capability(&pcie->pci,
-						      PCI_CAP_ID_EXP);
+	dw_pcie_get_pcie_cap(pci);
 
 	/* Clear Slot Clock Configuration bit if SRNS configuration */
 	if (pcie->enable_srns) {
-		val_16 = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base +
-					   PCI_EXP_LNKSTA);
+		val_16 = dw_pcie_readw_dbi(pci, pci->pcie_cap + PCI_EXP_LNKSTA);
 		val_16 &= ~PCI_EXP_LNKSTA_SLC;
-		dw_pcie_writew_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA,
-				   val_16);
+		dw_pcie_writew_dbi(pci, pci->pcie_cap + PCI_EXP_LNKSTA, val_16);
 	}
 
 	clk_set_rate(pcie->core_clk, GEN4_CORE_CLK_FREQ);
-- 
2.34.1


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers
  2026-05-09 13:51 [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers Hans Zhang
                   ` (2 preceding siblings ...)
  2026-05-09 13:51 ` [PATCH 3/3] PCI: dwc: Simplify platform drivers using cached capability offset Hans Zhang
@ 2026-05-19 13:57 ` Manivannan Sadhasivam
  2026-05-19 16:09   ` Hans Zhang
  3 siblings, 1 reply; 10+ messages in thread
From: Manivannan Sadhasivam @ 2026-05-19 13:57 UTC (permalink / raw)
  To: Hans Zhang
  Cc: bhelgaas, lpieralisi, kwilczynski, jingoohan1, mx, linuxppc-dev,
	linux-amlogic, linux-rockchip, linux-arm-msm, sophgo,
	linux-riscv, spacemit, linux-tegra, linux-pci, linux-kernel

On Sat, May 09, 2026 at 09:51:49PM +0800, Hans Zhang wrote:
> 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. And some even search for the PCI_CAP_ID_EXP offset value within
> the suspend/resume functions.
> 

Sashiko has flagged some real issues with this series in accessing DBI space
very early and 'pci->pcie_cap' being 0.

Those needs to be fixed.

- Mani

> Add a cached pcie_cap field in struct dw_pcie and a helper
> dw_pcie_get_pcie_cap() to initialize it once at probe time. Then replace
> all explicit capability searches with the cached value across the
> entire dwc subtree.
> 
> Hans Zhang (3):
>   PCI: dwc: Add pcie_cap field and helper in designware header
>   PCI: dwc: Use cached PCIe capability offset in core
>   PCI: dwc: Simplify platform drivers using cached capability offset
> 
>  drivers/pci/controller/dwc/pci-imx6.c         |  6 +--
>  .../pci/controller/dwc/pci-layerscape-ep.c    |  4 +-
>  drivers/pci/controller/dwc/pci-meson.c        |  4 +-
>  .../pci/controller/dwc/pcie-designware-ep.c   |  4 +-
>  .../pci/controller/dwc/pcie-designware-host.c |  4 +-
>  drivers/pci/controller/dwc/pcie-designware.c  | 16 +++---
>  drivers/pci/controller/dwc/pcie-designware.h  | 17 +++++++
>  drivers/pci/controller/dwc/pcie-dw-rockchip.c | 15 +++---
>  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        | 24 ++++-----
>  drivers/pci/controller/dwc/pcie-sophgo.c      |  8 ++-
>  drivers/pci/controller/dwc/pcie-spacemit-k1.c |  5 +-
>  drivers/pci/controller/dwc/pcie-spear13xx.c   |  6 +--
>  drivers/pci/controller/dwc/pcie-tegra194.c    | 51 +++++++------------
>  17 files changed, 85 insertions(+), 97 deletions(-)
> 
> 
> base-commit: 70390501d1944d4e5b8f7352be180fceb3a44132
> -- 
> 2.34.1
> 

-- 
மணிவண்ணன் சதாசிவம்

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers
  2026-05-19 13:57 ` [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers Manivannan Sadhasivam
@ 2026-05-19 16:09   ` Hans Zhang
  2026-05-19 16:15     ` Manivannan Sadhasivam
  0 siblings, 1 reply; 10+ messages in thread
From: Hans Zhang @ 2026-05-19 16:09 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: bhelgaas, lpieralisi, kwilczynski, jingoohan1, mx, linuxppc-dev,
	linux-amlogic, linux-rockchip, linux-arm-msm, sophgo,
	linux-riscv, spacemit, linux-tegra, linux-pci, linux-kernel



On 5/19/26 21:57, Manivannan Sadhasivam wrote:
> On Sat, May 09, 2026 at 09:51:49PM +0800, Hans Zhang wrote:
>> 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. And some even search for the PCI_CAP_ID_EXP offset value within
>> the suspend/resume functions.
>>
> 
> Sashiko has flagged some real issues with this series in accessing DBI space
> very early and 'pci->pcie_cap' being 0.


Hi Mani,

We have discussed this issue in the Cadence driver. I think it won't 
cause any problems. Specifically as follows:

https://lore.kernel.org/linux-pci/5823faec-d972-4c77-90ec-a215c686e0a8@163.com/
"""
As per PCIe r7.0, sec 7.5.1.1.11, Since all PCI Express Functions are 
required to implement the PCI Express Capability structure, which
must be included somewhere in this linked list.
"""



Bjorn also responded as follows:
https://lore.kernel.org/linux-pci/20260505212306.GA744158@bhelgaas/
"""
It's true that all Root Ports must have a PCIe Capability.
"""



Mani, should I continue to make the judgment that 'pci->pcie_cap' might 
be 0 as per your instructions?



Best regards,
Hans


> 
> Those needs to be fixed.
> 
> - Mani
> 
>> Add a cached pcie_cap field in struct dw_pcie and a helper
>> dw_pcie_get_pcie_cap() to initialize it once at probe time. Then replace
>> all explicit capability searches with the cached value across the
>> entire dwc subtree.
>>
>> Hans Zhang (3):
>>    PCI: dwc: Add pcie_cap field and helper in designware header
>>    PCI: dwc: Use cached PCIe capability offset in core
>>    PCI: dwc: Simplify platform drivers using cached capability offset
>>
>>   drivers/pci/controller/dwc/pci-imx6.c         |  6 +--
>>   .../pci/controller/dwc/pci-layerscape-ep.c    |  4 +-
>>   drivers/pci/controller/dwc/pci-meson.c        |  4 +-
>>   .../pci/controller/dwc/pcie-designware-ep.c   |  4 +-
>>   .../pci/controller/dwc/pcie-designware-host.c |  4 +-
>>   drivers/pci/controller/dwc/pcie-designware.c  | 16 +++---
>>   drivers/pci/controller/dwc/pcie-designware.h  | 17 +++++++
>>   drivers/pci/controller/dwc/pcie-dw-rockchip.c | 15 +++---
>>   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        | 24 ++++-----
>>   drivers/pci/controller/dwc/pcie-sophgo.c      |  8 ++-
>>   drivers/pci/controller/dwc/pcie-spacemit-k1.c |  5 +-
>>   drivers/pci/controller/dwc/pcie-spear13xx.c   |  6 +--
>>   drivers/pci/controller/dwc/pcie-tegra194.c    | 51 +++++++------------
>>   17 files changed, 85 insertions(+), 97 deletions(-)
>>
>>
>> base-commit: 70390501d1944d4e5b8f7352be180fceb3a44132
>> -- 
>> 2.34.1
>>
> 


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers
  2026-05-19 16:09   ` Hans Zhang
@ 2026-05-19 16:15     ` Manivannan Sadhasivam
  2026-05-19 16:27       ` Hans Zhang
  0 siblings, 1 reply; 10+ messages in thread
From: Manivannan Sadhasivam @ 2026-05-19 16:15 UTC (permalink / raw)
  To: Hans Zhang
  Cc: bhelgaas, lpieralisi, kwilczynski, jingoohan1, mx, linuxppc-dev,
	linux-amlogic, linux-rockchip, linux-arm-msm, sophgo,
	linux-riscv, spacemit, linux-tegra, linux-pci, linux-kernel

On Wed, May 20, 2026 at 12:09:28AM +0800, Hans Zhang wrote:
> 
> 
> On 5/19/26 21:57, Manivannan Sadhasivam wrote:
> > On Sat, May 09, 2026 at 09:51:49PM +0800, Hans Zhang wrote:
> > > 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. And some even search for the PCI_CAP_ID_EXP offset value within
> > > the suspend/resume functions.
> > > 
> > 
> > Sashiko has flagged some real issues with this series in accessing DBI space
> > very early and 'pci->pcie_cap' being 0.
> 
> 
> Hi Mani,
> 
> We have discussed this issue in the Cadence driver. I think it won't cause
> any problems. Specifically as follows:
> 
> https://lore.kernel.org/linux-pci/5823faec-d972-4c77-90ec-a215c686e0a8@163.com/
> """
> As per PCIe r7.0, sec 7.5.1.1.11, Since all PCI Express Functions are
> required to implement the PCI Express Capability structure, which
> must be included somewhere in this linked list.
> """
> 
> 
> 
> Bjorn also responded as follows:
> https://lore.kernel.org/linux-pci/20260505212306.GA744158@bhelgaas/
> """
> It's true that all Root Ports must have a PCIe Capability.
> """
> 

Ok, what about reading the DBI registers very early?

- Mani

-- 
மணிவண்ணன் சதாசிவம்

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers
  2026-05-19 16:15     ` Manivannan Sadhasivam
@ 2026-05-19 16:27       ` Hans Zhang
  2026-05-19 16:49         ` Manivannan Sadhasivam
  0 siblings, 1 reply; 10+ messages in thread
From: Hans Zhang @ 2026-05-19 16:27 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: bhelgaas, lpieralisi, kwilczynski, jingoohan1, mx, linuxppc-dev,
	linux-amlogic, linux-rockchip, linux-arm-msm, sophgo,
	linux-riscv, spacemit, linux-tegra, linux-pci, linux-kernel



On 5/20/26 00:15, Manivannan Sadhasivam wrote:
> On Wed, May 20, 2026 at 12:09:28AM +0800, Hans Zhang wrote:
>>
>>
>> On 5/19/26 21:57, Manivannan Sadhasivam wrote:
>>> On Sat, May 09, 2026 at 09:51:49PM +0800, Hans Zhang wrote:
>>>> 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. And some even search for the PCI_CAP_ID_EXP offset value within
>>>> the suspend/resume functions.
>>>>
>>>
>>> Sashiko has flagged some real issues with this series in accessing DBI space
>>> very early and 'pci->pcie_cap' being 0.
>>
>>
>> Hi Mani,
>>
>> We have discussed this issue in the Cadence driver. I think it won't cause
>> any problems. Specifically as follows:
>>
>> https://lore.kernel.org/linux-pci/5823faec-d972-4c77-90ec-a215c686e0a8@163.com/
>> """
>> As per PCIe r7.0, sec 7.5.1.1.11, Since all PCI Express Functions are
>> required to implement the PCI Express Capability structure, which
>> must be included somewhere in this linked list.
>> """
>>
>>
>>
>> Bjorn also responded as follows:
>> https://lore.kernel.org/linux-pci/20260505212306.GA744158@bhelgaas/
>> """
>> It's true that all Root Ports must have a PCIe Capability.
>> """
>>
> 
> Ok, what about reading the DBI registers very early?

Hi Mani,

Yes. I have performed the DBI read register operation at the very 
beginning of the following code.


dw_pcie_ep_init()
   dw_pcie_get_pcie_cap(pci);

dw_pcie_host_init
   dw_pcie_get_pcie_cap(pci);


However, for some glue drivers, they need to configure the registers of 
the PCIe Express Capability earlier than calling 
dw_pcie_host_init()/dw_pcie_ep_init(). So, for example, in the file: 
drivers/pci/controller/dwc/pcie-tegra194.c. Here, it is necessary to 
find the value of 'pci->pcie_cap' earlier. Then, 
dw_pcie_host_init()/dw_pcie_ep_init() will no longer search for the 
offset value of the PCIe Express Capability.


Best regards,
Hans


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers
  2026-05-19 16:27       ` Hans Zhang
@ 2026-05-19 16:49         ` Manivannan Sadhasivam
  2026-05-19 16:52           ` Hans Zhang
  0 siblings, 1 reply; 10+ messages in thread
From: Manivannan Sadhasivam @ 2026-05-19 16:49 UTC (permalink / raw)
  To: Hans Zhang
  Cc: bhelgaas, lpieralisi, kwilczynski, jingoohan1, mx, linuxppc-dev,
	linux-amlogic, linux-rockchip, linux-arm-msm, sophgo,
	linux-riscv, spacemit, linux-tegra, linux-pci, linux-kernel

On Wed, May 20, 2026 at 12:27:21AM +0800, Hans Zhang wrote:
> 
> 
> On 5/20/26 00:15, Manivannan Sadhasivam wrote:
> > On Wed, May 20, 2026 at 12:09:28AM +0800, Hans Zhang wrote:
> > > 
> > > 
> > > On 5/19/26 21:57, Manivannan Sadhasivam wrote:
> > > > On Sat, May 09, 2026 at 09:51:49PM +0800, Hans Zhang wrote:
> > > > > 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. And some even search for the PCI_CAP_ID_EXP offset value within
> > > > > the suspend/resume functions.
> > > > > 
> > > > 
> > > > Sashiko has flagged some real issues with this series in accessing DBI space
> > > > very early and 'pci->pcie_cap' being 0.
> > > 
> > > 
> > > Hi Mani,
> > > 
> > > We have discussed this issue in the Cadence driver. I think it won't cause
> > > any problems. Specifically as follows:
> > > 
> > > https://lore.kernel.org/linux-pci/5823faec-d972-4c77-90ec-a215c686e0a8@163.com/
> > > """
> > > As per PCIe r7.0, sec 7.5.1.1.11, Since all PCI Express Functions are
> > > required to implement the PCI Express Capability structure, which
> > > must be included somewhere in this linked list.
> > > """
> > > 
> > > 
> > > 
> > > Bjorn also responded as follows:
> > > https://lore.kernel.org/linux-pci/20260505212306.GA744158@bhelgaas/
> > > """
> > > It's true that all Root Ports must have a PCIe Capability.
> > > """
> > > 
> > 
> > Ok, what about reading the DBI registers very early?
> 
> Hi Mani,
> 
> Yes. I have performed the DBI read register operation at the very beginning
> of the following code.
> 
> 
> dw_pcie_ep_init()
>   dw_pcie_get_pcie_cap(pci);
> 
> dw_pcie_host_init
>   dw_pcie_get_pcie_cap(pci);
> 

These both calls will cause crash on a lot of platforms because these will be
reading the DBI registers while the resources are not enabled.

- Mani

-- 
மணிவண்ணன் சதாசிவம்

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers
  2026-05-19 16:49         ` Manivannan Sadhasivam
@ 2026-05-19 16:52           ` Hans Zhang
  0 siblings, 0 replies; 10+ messages in thread
From: Hans Zhang @ 2026-05-19 16:52 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: bhelgaas, lpieralisi, kwilczynski, jingoohan1, mx, linuxppc-dev,
	linux-amlogic, linux-rockchip, linux-arm-msm, sophgo,
	linux-riscv, spacemit, linux-tegra, linux-pci, linux-kernel



On 5/20/26 00:49, Manivannan Sadhasivam wrote:
> On Wed, May 20, 2026 at 12:27:21AM +0800, Hans Zhang wrote:
>>
>>
>> On 5/20/26 00:15, Manivannan Sadhasivam wrote:
>>> On Wed, May 20, 2026 at 12:09:28AM +0800, Hans Zhang wrote:
>>>>
>>>>
>>>> On 5/19/26 21:57, Manivannan Sadhasivam wrote:
>>>>> On Sat, May 09, 2026 at 09:51:49PM +0800, Hans Zhang wrote:
>>>>>> 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. And some even search for the PCI_CAP_ID_EXP offset value within
>>>>>> the suspend/resume functions.
>>>>>>
>>>>>
>>>>> Sashiko has flagged some real issues with this series in accessing DBI space
>>>>> very early and 'pci->pcie_cap' being 0.
>>>>
>>>>
>>>> Hi Mani,
>>>>
>>>> We have discussed this issue in the Cadence driver. I think it won't cause
>>>> any problems. Specifically as follows:
>>>>
>>>> https://lore.kernel.org/linux-pci/5823faec-d972-4c77-90ec-a215c686e0a8@163.com/
>>>> """
>>>> As per PCIe r7.0, sec 7.5.1.1.11, Since all PCI Express Functions are
>>>> required to implement the PCI Express Capability structure, which
>>>> must be included somewhere in this linked list.
>>>> """
>>>>
>>>>
>>>>
>>>> Bjorn also responded as follows:
>>>> https://lore.kernel.org/linux-pci/20260505212306.GA744158@bhelgaas/
>>>> """
>>>> It's true that all Root Ports must have a PCIe Capability.
>>>> """
>>>>
>>>
>>> Ok, what about reading the DBI registers very early?
>>
>> Hi Mani,
>>
>> Yes. I have performed the DBI read register operation at the very beginning
>> of the following code.
>>
>>
>> dw_pcie_ep_init()
>>    dw_pcie_get_pcie_cap(pci);
>>
>> dw_pcie_host_init
>>    dw_pcie_get_pcie_cap(pci);
>>
> 
> These both calls will cause crash on a lot of platforms because these will be
> reading the DBI registers while the resources are not enabled.

Hi Mani,

Next, I will check all the DBI register-related issues. It will be fixed 
in the next version. Thank you very much.

Best regards,
Hans


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-05-19 16:53 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-09 13:51 [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers Hans Zhang
2026-05-09 13:51 ` [PATCH 1/3] PCI: dwc: Add pcie_cap field and helper in designware header Hans Zhang
2026-05-09 13:51 ` [PATCH 2/3] PCI: dwc: Use cached PCIe capability offset in core Hans Zhang
2026-05-09 13:51 ` [PATCH 3/3] PCI: dwc: Simplify platform drivers using cached capability offset Hans Zhang
2026-05-19 13:57 ` [PATCH 0/3] PCI: dwc: Cache PCIe capability offset and simplify drivers Manivannan Sadhasivam
2026-05-19 16:09   ` Hans Zhang
2026-05-19 16:15     ` Manivannan Sadhasivam
2026-05-19 16:27       ` Hans Zhang
2026-05-19 16:49         ` Manivannan Sadhasivam
2026-05-19 16:52           ` Hans Zhang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®