mirror of
https://github.com/torvalds/linux.git
synced 2026-09-26 10:02:02 +02:00
PCI: host-generic: Move legacy DT binding fallback decision to caller of pci_host_common_parse_ports()
pci_host_common_parse_ports() returns -ENODEV if the bridge nodes (RP) are not present or PERST# is only found in the Root Complex node. Then the callers (currently just pci-imx6) assume that they need to fall back to parsing the legacy DT binding. But this behavior won't scale across Root Complex designs because PERST# is not the only optional property that the callers would need to consider for falling back to legacy binding. There could be many properties and the API cannot incorporate all of them. So to keep the API implementation simple, just return 0 when bridge nodes were not found. Then it is up to the caller to use its own logic to decide whether to fall back to legacy binding or not. Since there is only one caller now, update the caller to skip -ENODEV check and check for the PERST# GPIO in any of the bridge nodes and fall back to legacy binding if not found. Signed-off-by: Sherry Sun <sherry.sun@nxp.com> [mani: squashed imx6 patch to avoid bisectability issue, commit message] Signed-off-by: Manivannan Sadhasivam <mani@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Richard Zhu <hongxing.zhu@nxp.com> Link: https://patch.msgid.link/20260525065443.2338629-2-sherry.sun@oss.nxp.com
This commit is contained in:
parent
dc59e4fea9
commit
3567bcf0e9
|
|
@ -1318,6 +1318,18 @@ static void imx_pcie_assert_perst(struct imx_pcie *imx_pcie, bool assert)
|
|||
}
|
||||
}
|
||||
|
||||
static bool imx_pcie_perst_found(struct pci_host_bridge *bridge)
|
||||
{
|
||||
struct pci_host_port *port;
|
||||
|
||||
list_for_each_entry(port, &bridge->ports, list) {
|
||||
if (!list_empty(&port->perst))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int imx_pcie_host_init(struct dw_pcie_rp *pp)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
||||
|
|
@ -1330,15 +1342,12 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
|
|||
/* Parse Root Port nodes if present */
|
||||
ret = pci_host_common_parse_ports(dev, bridge);
|
||||
if (ret) {
|
||||
if (ret != -ENODEV) {
|
||||
dev_err(dev, "Failed to parse Root Port nodes: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
dev_err(dev, "Failed to parse Root Port nodes: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fall back to legacy binding for DT backwards
|
||||
* compatibility
|
||||
*/
|
||||
/* Fall back to legacy binding for DT backwards compatibility */
|
||||
if (!imx_pcie_perst_found(bridge)) {
|
||||
ret = imx_pcie_parse_legacy_binding(imx_pcie);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -108,8 +108,7 @@ static int pci_host_common_parse_perst(struct device *dev,
|
|||
* dependencies and the driver may fail to operate if required resources
|
||||
* are missing.
|
||||
*
|
||||
* Return: 0 on success, -ENODEV if PERST# found in RC node (legacy binding
|
||||
* should be used), Other negative error codes on failure.
|
||||
* Return: 0 on success, negative error codes on failure.
|
||||
*/
|
||||
static int pci_host_common_parse_port(struct device *dev,
|
||||
struct pci_host_bridge *bridge,
|
||||
|
|
@ -128,22 +127,6 @@ static int pci_host_common_parse_port(struct device *dev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* 1. PERST# found in RP or its child nodes - list is not empty,
|
||||
* continue
|
||||
*
|
||||
* 2. PERST# not found in RP/children, but found in RC node -
|
||||
* return -ENODEV to fallback legacy binding
|
||||
*
|
||||
* 3. PERST# not found anywhere - list is empty, continue (optional
|
||||
* PERST#)
|
||||
*/
|
||||
if (list_empty(&port->perst)) {
|
||||
if (of_property_present(dev->of_node, "reset-gpios") ||
|
||||
of_property_present(dev->of_node, "reset-gpio"))
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&port->list);
|
||||
list_add_tail(&port->list, &bridge->ports);
|
||||
|
||||
|
|
@ -158,13 +141,11 @@ static int pci_host_common_parse_port(struct device *dev,
|
|||
* Iterate through child nodes of the host bridge and parse Root Port
|
||||
* properties (currently only reset GPIOs).
|
||||
*
|
||||
* Return: 0 on success, -ENODEV if no ports found or PERST# found in RC
|
||||
* node (legacy binding should be used), Other negative error codes on
|
||||
* failure.
|
||||
* Return: 0 on success or ports not found, negative error codes on failure.
|
||||
*/
|
||||
int pci_host_common_parse_ports(struct device *dev, struct pci_host_bridge *bridge)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
int ret = 0;
|
||||
|
||||
for_each_available_child_of_node_scoped(dev->of_node, of_port) {
|
||||
if (!of_node_is_type(of_port, "pci"))
|
||||
|
|
@ -174,8 +155,8 @@ int pci_host_common_parse_ports(struct device *dev, struct pci_host_bridge *brid
|
|||
goto err_cleanup;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
if (list_empty(&bridge->ports))
|
||||
return 0;
|
||||
|
||||
return devm_add_action_or_reset(dev, pci_host_common_delete_ports,
|
||||
&bridge->ports);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user