diff options
| author | Bjorn Helgaas <bhelgaas@google.com> | 2026-04-13 12:50:07 -0500 |
|---|---|---|
| committer | Bjorn Helgaas <bhelgaas@google.com> | 2026-04-13 12:50:07 -0500 |
| commit | 736b677ff42837accf40784d5bd71a1d01f8fc87 (patch) | |
| tree | c5fcb2656fc3388d6579aa8e60760bc6aa5c4e67 /drivers | |
| parent | 8153aaf6b9e798a89d5939cf55f44a1815fe3252 (diff) | |
| parent | c8b610341914cb62899e31b41f724b5c4831a645 (diff) | |
| download | lwn-736b677ff42837accf40784d5bd71a1d01f8fc87.tar.gz lwn-736b677ff42837accf40784d5bd71a1d01f8fc87.zip | |
Merge branch 'pci/controller/max-link-speed'
- Add pcie_get_link_speed() to encapsulate and bounds-check
pcie_link_speed[] accesses (Hans Zhang)
- Validate max-link-speed from DT in j721e, brcmstb, mediatek-gen3, rzg3s
(where the actual controller constraints are known), and remove it from
the generic OF DT accessor (Hans Zhang)
* pci/controller/max-link-speed:
PCI: of: Remove max-link-speed generation validation
PCI: controller: Validate max-link-speed
PCI: j721e: Validate max-link-speed from DT
PCI: dwc: Use pcie_get_link_speed() helper for safe array access
PCI: Add pcie_get_link_speed() helper for safe array access
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/pci/controller/cadence/pci-j721e.c | 3 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware-host.c | 2 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware.c | 2 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-qcom-common.c | 2 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-qcom-ep.c | 4 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-qcom.c | 6 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-tegra194.c | 2 | ||||
| -rw-r--r-- | drivers/pci/controller/pcie-brcmstb.c | 5 | ||||
| -rw-r--r-- | drivers/pci/controller/pcie-mediatek-gen3.c | 2 | ||||
| -rw-r--r-- | drivers/pci/controller/pcie-rzg3s-host.c | 2 | ||||
| -rw-r--r-- | drivers/pci/of.c | 19 | ||||
| -rw-r--r-- | drivers/pci/pci.h | 2 | ||||
| -rw-r--r-- | drivers/pci/probe.c | 16 |
13 files changed, 41 insertions, 26 deletions
diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c index 6f2501479c70..bfdfe98d5aba 100644 --- a/drivers/pci/controller/cadence/pci-j721e.c +++ b/drivers/pci/controller/cadence/pci-j721e.c @@ -202,7 +202,8 @@ static int j721e_pcie_set_link_speed(struct j721e_pcie *pcie, int ret; link_speed = of_pci_get_max_link_speed(np); - if (link_speed < 2) + if ((link_speed < 2) || + (pcie_get_link_speed(link_speed) == PCI_SPEED_UNKNOWN)) link_speed = 2; val = link_speed - 1; diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 6ae6189e9b8a..0e05c5280344 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -1081,7 +1081,7 @@ static void dw_pcie_program_presets(struct dw_pcie_rp *pp, enum pci_bus_speed sp static void dw_pcie_config_presets(struct dw_pcie_rp *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - enum pci_bus_speed speed = pcie_link_speed[pci->max_link_speed]; + enum pci_bus_speed speed = pcie_get_link_speed(pci->max_link_speed); /* * Lane equalization settings need to be applied for all data rates the diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index 5741c09dde7f..06792ba92aa7 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -861,7 +861,7 @@ static void dw_pcie_link_set_max_speed(struct dw_pcie *pci) ctrl2 = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCTL2); ctrl2 &= ~PCI_EXP_LNKCTL2_TLS; - switch (pcie_link_speed[pci->max_link_speed]) { + switch (pcie_get_link_speed(pci->max_link_speed)) { case PCIE_SPEED_2_5GT: link_speed = PCI_EXP_LNKCTL2_TLS_2_5GT; break; diff --git a/drivers/pci/controller/dwc/pcie-qcom-common.c b/drivers/pci/controller/dwc/pcie-qcom-common.c index 01c5387e53bf..5aa73c628737 100644 --- a/drivers/pci/controller/dwc/pcie-qcom-common.c +++ b/drivers/pci/controller/dwc/pcie-qcom-common.c @@ -22,7 +22,7 @@ void qcom_pcie_common_set_equalization(struct dw_pcie *pci) * applied. */ - for (speed = PCIE_SPEED_8_0GT; speed <= pcie_link_speed[pci->max_link_speed]; speed++) { + for (speed = PCIE_SPEED_8_0GT; speed <= pcie_get_link_speed(pci->max_link_speed); speed++) { if (speed > PCIE_SPEED_32_0GT) { dev_warn(dev, "Skipped equalization settings for unsupported data rate\n"); break; diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c index 8e8c58a42bc3..257c2bcb5f76 100644 --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c @@ -152,7 +152,7 @@ #define WAKE_DELAY_US 2000 /* 2 ms */ #define QCOM_PCIE_LINK_SPEED_TO_BW(speed) \ - Mbps_to_icc(PCIE_SPEED2MBS_ENC(pcie_link_speed[speed])) + Mbps_to_icc(PCIE_SPEED2MBS_ENC(pcie_get_link_speed(speed))) #define to_pcie_ep(x) dev_get_drvdata((x)->dev) @@ -531,7 +531,7 @@ skip_resources_enable: qcom_pcie_common_set_equalization(pci); - if (pcie_link_speed[pci->max_link_speed] == PCIE_SPEED_16_0GT) + if (pcie_get_link_speed(pci->max_link_speed) == PCIE_SPEED_16_0GT) qcom_pcie_common_set_16gt_lane_margining(pci); /* diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 67a16af69ddc..5c7c105bb745 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -170,7 +170,7 @@ #define QCOM_PCIE_CRC8_POLYNOMIAL (BIT(2) | BIT(1) | BIT(0)) #define QCOM_PCIE_LINK_SPEED_TO_BW(speed) \ - Mbps_to_icc(PCIE_SPEED2MBS_ENC(pcie_link_speed[speed])) + Mbps_to_icc(PCIE_SPEED2MBS_ENC(pcie_get_link_speed(speed))) struct qcom_pcie_resources_1_0_0 { struct clk_bulk_data *clks; @@ -320,7 +320,7 @@ static int qcom_pcie_start_link(struct dw_pcie *pci) qcom_pcie_common_set_equalization(pci); - if (pcie_link_speed[pci->max_link_speed] == PCIE_SPEED_16_0GT) + if (pcie_get_link_speed(pci->max_link_speed) == PCIE_SPEED_16_0GT) qcom_pcie_common_set_16gt_lane_margining(pci); /* Enable Link Training state machine */ @@ -1579,7 +1579,7 @@ static void qcom_pcie_icc_opp_update(struct qcom_pcie *pcie) ret); } } else if (pcie->use_pm_opp) { - freq_mbps = pcie_dev_speed_mbps(pcie_link_speed[speed]); + freq_mbps = pcie_dev_speed_mbps(pcie_get_link_speed(speed)); if (freq_mbps < 0) return; diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c index ea7a6256450c..ab1a259fc763 100644 --- a/drivers/pci/controller/dwc/pcie-tegra194.c +++ b/drivers/pci/controller/dwc/pcie-tegra194.c @@ -310,7 +310,7 @@ static void tegra_pcie_icc_set(struct tegra_pcie_dw *pcie) speed = FIELD_GET(PCI_EXP_LNKSTA_CLS, val); width = FIELD_GET(PCI_EXP_LNKSTA_NLW, val); - val = width * PCIE_SPEED2MBS_ENC(pcie_link_speed[speed]); + val = width * PCIE_SPEED2MBS_ENC(pcie_get_link_speed(speed)); if (icc_set_bw(pcie->icc_path, Mbps_to_icc(val), 0)) dev_err(pcie->dev, "can't set bw[%u]\n", val); diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c index 062f55690012..714bcab97b60 100644 --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c @@ -1442,7 +1442,7 @@ static int brcm_pcie_start_link(struct brcm_pcie *pcie) cls = FIELD_GET(PCI_EXP_LNKSTA_CLS, lnksta); nlw = FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta); dev_info(dev, "link up, %s x%u %s\n", - pci_speed_string(pcie_link_speed[cls]), nlw, + pci_speed_string(pcie_get_link_speed(cls)), nlw, ssc_good ? "(SSC)" : "(!SSC)"); return 0; @@ -2072,7 +2072,8 @@ static int brcm_pcie_probe(struct platform_device *pdev) return PTR_ERR(pcie->clk); ret = of_pci_get_max_link_speed(np); - pcie->gen = (ret < 0) ? 0 : ret; + if (pcie_get_link_speed(ret) == PCI_SPEED_UNKNOWN) + pcie->gen = 0; pcie->ssc = of_property_read_bool(np, "brcm,enable-ssc"); diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c index 75ddb8bee168..3b903ef7d3cf 100644 --- a/drivers/pci/controller/pcie-mediatek-gen3.c +++ b/drivers/pci/controller/pcie-mediatek-gen3.c @@ -1150,7 +1150,7 @@ static int mtk_pcie_setup(struct mtk_gen3_pcie *pcie) return err; err = of_pci_get_max_link_speed(pcie->dev->of_node); - if (err) { + if (pcie_get_link_speed(err) != PCI_SPEED_UNKNOWN) { /* Get the maximum speed supported by the controller */ max_speed = mtk_pcie_get_controller_max_link_speed(pcie); diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/controller/pcie-rzg3s-host.c index 2809112e6317..00a11f986117 100644 --- a/drivers/pci/controller/pcie-rzg3s-host.c +++ b/drivers/pci/controller/pcie-rzg3s-host.c @@ -966,7 +966,7 @@ static int rzg3s_pcie_set_max_link_speed(struct rzg3s_pcie_host *host) ls = readw_relaxed(host->pcie + pcie_cap + PCI_EXP_LNKSTA); cs2 = readl_relaxed(host->axi + RZG3S_PCI_PCSTAT2); - switch (pcie_link_speed[host->max_link_speed]) { + switch (pcie_get_link_speed(host->max_link_speed)) { case PCIE_SPEED_5_0GT: max_supported_link_speeds = GENMASK(PCI_EXP_LNKSTA_CLS_5_0GB - 1, 0); link_speed = PCI_EXP_LNKCTL2_TLS_5_0GT; diff --git a/drivers/pci/of.c b/drivers/pci/of.c index 9f8eb5df279e..c216701c75dd 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c @@ -875,24 +875,19 @@ EXPORT_SYMBOL_GPL(of_pci_supply_present); * of_pci_get_max_link_speed - Find the maximum link speed of the given device node. * @node: Device tree node with the maximum link speed information. * - * This function will try to find the limitation of link speed by finding - * a property called "max-link-speed" of the given device node. + * This function will try to read the "max-link-speed" property of the given + * device tree node. It does NOT validate the value of the property. * - * Return: - * * > 0 - On success, a maximum link speed. - * * -EINVAL - Invalid "max-link-speed" property value, or failure to access - * the property of the device tree node. - * - * Returns the associated max link speed from DT, or a negative value if the - * required property is not found or is invalid. + * Return: Maximum link speed value on success, errno on failure. */ int of_pci_get_max_link_speed(struct device_node *node) { u32 max_link_speed; + int ret; - if (of_property_read_u32(node, "max-link-speed", &max_link_speed) || - max_link_speed == 0 || max_link_speed > 4) - return -EINVAL; + ret = of_property_read_u32(node, "max-link-speed", &max_link_speed); + if (ret) + return ret; return max_link_speed; } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 9540f1f1709a..4a14f88e543a 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -108,6 +108,8 @@ struct pcie_tlp_log; PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) extern const unsigned char pcie_link_speed[]; +unsigned char pcie_get_link_speed(unsigned int speed); + extern bool pci_early_dump; extern struct mutex pci_rescan_remove_lock; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 675713548431..0cb6d9c35f1d 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -772,6 +772,22 @@ const unsigned char pcie_link_speed[] = { }; EXPORT_SYMBOL_GPL(pcie_link_speed); +/** + * pcie_get_link_speed - Get speed value from PCIe generation number + * @speed: PCIe speed (1-based: 1 = 2.5GT, 2 = 5GT, ...) + * + * Returns the speed value (e.g., PCIE_SPEED_2_5GT) if @speed is valid, + * otherwise returns PCI_SPEED_UNKNOWN. + */ +unsigned char pcie_get_link_speed(unsigned int speed) +{ + if (speed >= ARRAY_SIZE(pcie_link_speed)) + return PCI_SPEED_UNKNOWN; + + return pcie_link_speed[speed]; +} +EXPORT_SYMBOL_GPL(pcie_get_link_speed); + const char *pci_speed_string(enum pci_bus_speed speed) { /* Indexed by the pci_bus_speed enum */ |
