[PATCH v6 2/5] PCI: dwc: Allow glue drivers to return mutable EPC features
From: Koichiro Den <hidden>
Date: 2026-01-13 02:37:30
Also in:
imx, linux-arm-msm, linux-omap, linux-pci, linux-renesas-soc, linux-rockchip, linux-tegra, lkml
Subsystem:
arm/qualcomm mailing list, arm/rockchip soc support, pci driver for freescale layerscape, pci driver for imx6, pci driver for renesas r-car, pci driver for stm32mp25, pci driver for synopsys designware, pci driver for ti dra7xx/j721e, pci native host bridge and endpoint drivers, pci subsystem, pcie driver for axis artpec, pcie driver for intel keem bay, pcie driver for socionext uniphier, pcie endpoint driver for qualcomm, the rest · Maintainers:
Heiko Stuebner, Minghuan Lian, Mingkai Hu, Roy Zang, Richard Zhu, Lucas Stach, Marek Vasut, Yoshihiro Shimoda, Christian Bruel, Jingoo Han, Manivannan Sadhasivam, Vignesh Raghavendra, Lorenzo Pieralisi, Krzysztof Wilczyński, Bjorn Helgaas, Jesper Nilsson, Srikanth Thokala, Kunihiko Hayashi, Linus Torvalds
The DesignWare EP midlayer needs to advertise additional capabilities at the DWC layer (e.g. subrange_mapping) without duplicating the same bit in every DWC-based glue driver and without copying feature structures. Change dw_pcie_ep_ops.get_features() to return a mutable struct pci_epc_features * and update all DWC-based glue drivers accordingly. The DWC midlayer can then adjust/augment the returned features while still exposing a const struct pci_epc_features * to the PCI EPC core. No functional change on its own. Suggested-by: Niklas Cassel <cassel@kernel.org> Signed-off-by: Koichiro Den <redacted> --- drivers/pci/controller/dwc/pci-dra7xx.c | 4 +- drivers/pci/controller/dwc/pci-imx6.c | 10 ++-- drivers/pci/controller/dwc/pci-keystone.c | 4 +- .../pci/controller/dwc/pci-layerscape-ep.c | 2 +- drivers/pci/controller/dwc/pcie-artpec6.c | 4 +- .../pci/controller/dwc/pcie-designware-plat.c | 4 +- drivers/pci/controller/dwc/pcie-designware.h | 2 +- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 8 +-- drivers/pci/controller/dwc/pcie-keembay.c | 4 +- drivers/pci/controller/dwc/pcie-qcom-ep.c | 4 +- drivers/pci/controller/dwc/pcie-rcar-gen4.c | 4 +- drivers/pci/controller/dwc/pcie-stm32-ep.c | 4 +- drivers/pci/controller/dwc/pcie-tegra194.c | 4 +- drivers/pci/controller/dwc/pcie-uniphier-ep.c | 58 ++++++++++--------- 14 files changed, 60 insertions(+), 56 deletions(-)
diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c
index 01cfd9aeb0b8..e67f8b7b56cb 100644
--- a/drivers/pci/controller/dwc/pci-dra7xx.c
+++ b/drivers/pci/controller/dwc/pci-dra7xx.c@@ -423,12 +423,12 @@ static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, return 0; } -static const struct pci_epc_features dra7xx_pcie_epc_features = { +static struct pci_epc_features dra7xx_pcie_epc_features = { .linkup_notifier = true, .msi_capable = true, }; -static const struct pci_epc_features* +static struct pci_epc_features* dra7xx_pcie_get_features(struct dw_pcie_ep *ep) { return &dra7xx_pcie_epc_features;
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 4668fc9648bf..fe1de30b3df6 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c@@ -131,7 +131,7 @@ struct imx_pcie_drvdata { const u32 ltssm_mask; const u32 mode_off[IMX_PCIE_MAX_INSTANCES]; const u32 mode_mask[IMX_PCIE_MAX_INSTANCES]; - const struct pci_epc_features *epc_features; + struct pci_epc_features *epc_features; int (*init_phy)(struct imx_pcie *pcie); int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable); int (*core_reset)(struct imx_pcie *pcie, bool assert);
@@ -1386,7 +1386,7 @@ static int imx_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, return 0; } -static const struct pci_epc_features imx8m_pcie_epc_features = { +static struct pci_epc_features imx8m_pcie_epc_features = { .msi_capable = true, .bar[BAR_1] = { .type = BAR_RESERVED, }, .bar[BAR_3] = { .type = BAR_RESERVED, },
@@ -1395,7 +1395,7 @@ static const struct pci_epc_features imx8m_pcie_epc_features = { .align = SZ_64K, }; -static const struct pci_epc_features imx8q_pcie_epc_features = { +static struct pci_epc_features imx8q_pcie_epc_features = { .msi_capable = true, .bar[BAR_1] = { .type = BAR_RESERVED, }, .bar[BAR_3] = { .type = BAR_RESERVED, },
@@ -1415,13 +1415,13 @@ static const struct pci_epc_features imx8q_pcie_epc_features = { * BAR4 | Enable | 32-bit | 1 MB | Programmable Size * BAR5 | Enable | 32-bit | 64 KB | Programmable Size */ -static const struct pci_epc_features imx95_pcie_epc_features = { +static struct pci_epc_features imx95_pcie_epc_features = { .msi_capable = true, .bar[BAR_1] = { .type = BAR_FIXED, .fixed_size = SZ_64K, }, .align = SZ_4K, }; -static const struct pci_epc_features* +static struct pci_epc_features* imx_pcie_ep_get_features(struct dw_pcie_ep *ep) { struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index f86d9111f863..4292007a9b3a 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c@@ -929,7 +929,7 @@ static int ks_pcie_am654_raise_irq(struct dw_pcie_ep *ep, u8 func_no, return 0; } -static const struct pci_epc_features ks_pcie_am654_epc_features = { +static struct pci_epc_features ks_pcie_am654_epc_features = { .msi_capable = true, .msix_capable = true, .bar[BAR_0] = { .type = BAR_RESERVED, },
@@ -941,7 +941,7 @@ static const struct pci_epc_features ks_pcie_am654_epc_features = { .align = SZ_64K, }; -static const struct pci_epc_features* +static struct pci_epc_features* ks_pcie_am654_get_features(struct dw_pcie_ep *ep) { return &ks_pcie_am654_epc_features;
diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index a4a800699f89..8d48413050ef 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c@@ -138,7 +138,7 @@ static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep *pcie, return 0; } -static const struct pci_epc_features* +static struct pci_epc_features* ls_pcie_ep_get_features(struct dw_pcie_ep *ep) { struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
diff --git a/drivers/pci/controller/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c
index f4a136ee2daf..84111d8257f2 100644
--- a/drivers/pci/controller/dwc/pcie-artpec6.c
+++ b/drivers/pci/controller/dwc/pcie-artpec6.c@@ -369,11 +369,11 @@ static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, return 0; } -static const struct pci_epc_features artpec6_pcie_epc_features = { +static struct pci_epc_features artpec6_pcie_epc_features = { .msi_capable = true, }; -static const struct pci_epc_features * +static struct pci_epc_features * artpec6_pcie_get_features(struct dw_pcie_ep *ep) { return &artpec6_pcie_epc_features;
diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c
index 12f41886c65d..60ada0eb838e 100644
--- a/drivers/pci/controller/dwc/pcie-designware-plat.c
+++ b/drivers/pci/controller/dwc/pcie-designware-plat.c@@ -60,12 +60,12 @@ static int dw_plat_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, return 0; } -static const struct pci_epc_features dw_plat_pcie_epc_features = { +static struct pci_epc_features dw_plat_pcie_epc_features = { .msi_capable = true, .msix_capable = true, }; -static const struct pci_epc_features* +static struct pci_epc_features* dw_plat_pcie_get_features(struct dw_pcie_ep *ep) { return &dw_plat_pcie_epc_features;
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index f87c67a7a482..4dda9a38d46b 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h@@ -449,7 +449,7 @@ struct dw_pcie_ep_ops { void (*init)(struct dw_pcie_ep *ep); int (*raise_irq)(struct dw_pcie_ep *ep, u8 func_no, unsigned int type, u16 interrupt_num); - const struct pci_epc_features* (*get_features)(struct dw_pcie_ep *ep); + struct pci_epc_features* (*get_features)(struct dw_pcie_ep *ep); /* * Provide a method to implement the different func config space * access for different platform, if different func have different
diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index 352f513ebf03..1f3c91368dc3 100644
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c@@ -100,7 +100,7 @@ struct rockchip_pcie { struct rockchip_pcie_of_data { enum dw_pcie_device_mode mode; - const struct pci_epc_features *epc_features; + struct pci_epc_features *epc_features; }; static int rockchip_pcie_readl_apb(struct rockchip_pcie *rockchip, u32 reg)
@@ -383,7 +383,7 @@ static int rockchip_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, return 0; } -static const struct pci_epc_features rockchip_pcie_epc_features_rk3568 = { +static struct pci_epc_features rockchip_pcie_epc_features_rk3568 = { .linkup_notifier = true, .msi_capable = true, .msix_capable = true,
@@ -403,7 +403,7 @@ static const struct pci_epc_features rockchip_pcie_epc_features_rk3568 = { * default.) If the host could write to BAR4, the iATU settings (for all other * BARs) would be overwritten, resulting in (all other BARs) no longer working. */ -static const struct pci_epc_features rockchip_pcie_epc_features_rk3588 = { +static struct pci_epc_features rockchip_pcie_epc_features_rk3588 = { .linkup_notifier = true, .msi_capable = true, .msix_capable = true,
@@ -416,7 +416,7 @@ static const struct pci_epc_features rockchip_pcie_epc_features_rk3588 = { .bar[BAR_5] = { .type = BAR_RESIZABLE, }, }; -static const struct pci_epc_features * +static struct pci_epc_features * rockchip_pcie_get_features(struct dw_pcie_ep *ep) { struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
diff --git a/drivers/pci/controller/dwc/pcie-keembay.c b/drivers/pci/controller/dwc/pcie-keembay.c
index 60e74ac782af..e6de5289329f 100644
--- a/drivers/pci/controller/dwc/pcie-keembay.c
+++ b/drivers/pci/controller/dwc/pcie-keembay.c@@ -308,7 +308,7 @@ static int keembay_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, } } -static const struct pci_epc_features keembay_pcie_epc_features = { +static struct pci_epc_features keembay_pcie_epc_features = { .msi_capable = true, .msix_capable = true, .bar[BAR_0] = { .only_64bit = true, },
@@ -320,7 +320,7 @@ static const struct pci_epc_features keembay_pcie_epc_features = { .align = SZ_16K, }; -static const struct pci_epc_features * +static struct pci_epc_features * keembay_pcie_get_features(struct dw_pcie_ep *ep) { return &keembay_pcie_epc_features;
diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c
index f1bc0ac81a92..6ad033301909 100644
--- a/drivers/pci/controller/dwc/pcie-qcom-ep.c
+++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c@@ -819,7 +819,7 @@ static void qcom_pcie_ep_init_debugfs(struct qcom_pcie_ep *pcie_ep) qcom_pcie_ep_link_transition_count); } -static const struct pci_epc_features qcom_pcie_epc_features = { +static struct pci_epc_features qcom_pcie_epc_features = { .linkup_notifier = true, .msi_capable = true, .align = SZ_4K,
@@ -829,7 +829,7 @@ static const struct pci_epc_features qcom_pcie_epc_features = { .bar[BAR_3] = { .type = BAR_RESERVED, }, }; -static const struct pci_epc_features * +static struct pci_epc_features * qcom_pcie_epc_get_features(struct dw_pcie_ep *pci_ep) { return &qcom_pcie_epc_features;
diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index 80778917d2dd..ff0c4af90eff 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c@@ -419,7 +419,7 @@ static int rcar_gen4_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, return 0; } -static const struct pci_epc_features rcar_gen4_pcie_epc_features = { +static struct pci_epc_features rcar_gen4_pcie_epc_features = { .msi_capable = true, .bar[BAR_1] = { .type = BAR_RESERVED, }, .bar[BAR_3] = { .type = BAR_RESERVED, },
@@ -428,7 +428,7 @@ static const struct pci_epc_features rcar_gen4_pcie_epc_features = { .align = SZ_1M, }; -static const struct pci_epc_features* +static struct pci_epc_features* rcar_gen4_pcie_ep_get_features(struct dw_pcie_ep *ep) { return &rcar_gen4_pcie_epc_features;
diff --git a/drivers/pci/controller/dwc/pcie-stm32-ep.c b/drivers/pci/controller/dwc/pcie-stm32-ep.c
index 2cecf32d2b0f..8a892def54f5 100644
--- a/drivers/pci/controller/dwc/pcie-stm32-ep.c
+++ b/drivers/pci/controller/dwc/pcie-stm32-ep.c@@ -69,12 +69,12 @@ static int stm32_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, } } -static const struct pci_epc_features stm32_pcie_epc_features = { +static struct pci_epc_features stm32_pcie_epc_features = { .msi_capable = true, .align = SZ_64K, }; -static const struct pci_epc_features* +static struct pci_epc_features* stm32_pcie_get_features(struct dw_pcie_ep *ep) { return &stm32_pcie_epc_features;
diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 0ddeef70726d..06f45a17e52c 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c@@ -1987,7 +1987,7 @@ static int tegra_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, return 0; } -static const struct pci_epc_features tegra_pcie_epc_features = { +static struct pci_epc_features tegra_pcie_epc_features = { .linkup_notifier = true, .msi_capable = true, .bar[BAR_0] = { .type = BAR_FIXED, .fixed_size = SZ_1M,
@@ -2000,7 +2000,7 @@ static const struct pci_epc_features tegra_pcie_epc_features = { .align = SZ_64K, }; -static const struct pci_epc_features* +static struct pci_epc_features* tegra_pcie_ep_get_features(struct dw_pcie_ep *ep) { return &tegra_pcie_epc_features;
diff --git a/drivers/pci/controller/dwc/pcie-uniphier-ep.c b/drivers/pci/controller/dwc/pcie-uniphier-ep.c
index d6e73811216e..ddb5ff70340c 100644
--- a/drivers/pci/controller/dwc/pcie-uniphier-ep.c
+++ b/drivers/pci/controller/dwc/pcie-uniphier-ep.c@@ -82,7 +82,7 @@ struct uniphier_pcie_ep_soc_data { bool has_gio; void (*init)(struct uniphier_pcie_ep_priv *priv); int (*wait)(struct uniphier_pcie_ep_priv *priv); - const struct pci_epc_features features; + struct pci_epc_features *features; }; #define to_uniphier_pcie(x) dev_get_drvdata((x)->dev)
@@ -273,13 +273,13 @@ static int uniphier_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, return 0; } -static const struct pci_epc_features* +static struct pci_epc_features* uniphier_pcie_get_features(struct dw_pcie_ep *ep) { struct dw_pcie *pci = to_dw_pcie_from_ep(ep); struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci); - return &priv->data->features; + return priv->data->features; } static const struct dw_pcie_ep_ops uniphier_pcie_ep_ops = {
@@ -415,40 +415,44 @@ static int uniphier_pcie_ep_probe(struct platform_device *pdev) return 0; } +static struct pci_epc_features uniphier_pro5_features = { + .linkup_notifier = false, + .msi_capable = true, + .msix_capable = false, + .align = 1 << 16, + .bar[BAR_0] = { .only_64bit = true, }, + .bar[BAR_1] = { .type = BAR_RESERVED, }, + .bar[BAR_2] = { .only_64bit = true, }, + .bar[BAR_3] = { .type = BAR_RESERVED, }, + .bar[BAR_4] = { .type = BAR_RESERVED, }, + .bar[BAR_5] = { .type = BAR_RESERVED, }, +}; + +static struct pci_epc_features uniphier_nx1_features = { + .linkup_notifier = false, + .msi_capable = true, + .msix_capable = false, + .align = 1 << 12, + .bar[BAR_0] = { .only_64bit = true, }, + .bar[BAR_1] = { .type = BAR_RESERVED, }, + .bar[BAR_2] = { .only_64bit = true, }, + .bar[BAR_3] = { .type = BAR_RESERVED, }, + .bar[BAR_4] = { .only_64bit = true, }, + .bar[BAR_5] = { .type = BAR_RESERVED, }, +}; + static const struct uniphier_pcie_ep_soc_data uniphier_pro5_data = { .has_gio = true, .init = uniphier_pcie_pro5_init_ep, .wait = NULL, - .features = { - .linkup_notifier = false, - .msi_capable = true, - .msix_capable = false, - .align = 1 << 16, - .bar[BAR_0] = { .only_64bit = true, }, - .bar[BAR_1] = { .type = BAR_RESERVED, }, - .bar[BAR_2] = { .only_64bit = true, }, - .bar[BAR_3] = { .type = BAR_RESERVED, }, - .bar[BAR_4] = { .type = BAR_RESERVED, }, - .bar[BAR_5] = { .type = BAR_RESERVED, }, - }, + .features = &uniphier_pro5_features, }; static const struct uniphier_pcie_ep_soc_data uniphier_nx1_data = { .has_gio = false, .init = uniphier_pcie_nx1_init_ep, .wait = uniphier_pcie_nx1_wait_ep, - .features = { - .linkup_notifier = false, - .msi_capable = true, - .msix_capable = false, - .align = 1 << 12, - .bar[BAR_0] = { .only_64bit = true, }, - .bar[BAR_1] = { .type = BAR_RESERVED, }, - .bar[BAR_2] = { .only_64bit = true, }, - .bar[BAR_3] = { .type = BAR_RESERVED, }, - .bar[BAR_4] = { .only_64bit = true, }, - .bar[BAR_5] = { .type = BAR_RESERVED, }, - }, + .features = &uniphier_nx1_features, }; static const struct of_device_id uniphier_pcie_ep_match[] = {
--
2.51.0