[PATCH 1/3] PCI: of: Fix handling of multi-level PCI devices

From: Mauro Carvalho Chehab
Date: Thu Aug 05 2021 - 04:29:15 EST


When the DT schema is like:

pcie@f4000000 {
pcie@0,0 {
pcie@1,0 {
};
pcie@5,0 {
};
pcie@7,0 {
};
};
};

The logic under pci_set_bus_of_node() will try to setup some
buses with a NULL node, causing it to register just a small
set of devices:

$ find /sys/devices/platform/soc/f4000000.pcie/ -name of_node
/sys/devices/platform/soc/f4000000.pcie/of_node
/sys/devices/platform/soc/f4000000.pcie/pci0000:00/0000:00:00.0/of_node
/sys/devices/platform/soc/f4000000.pcie/pci0000:00/0000:00:00.0/pci_bus/0000:01/of_node
/sys/devices/platform/soc/f4000000.pcie/pci0000:00/pci_bus/0000:00/of_node

On such case, it needs to go to the parent node, in order to register
everything:

$ find /sys/devices/platform/soc/f4000000.pcie/ -name of_node
/sys/devices/platform/soc/f4000000.pcie/of_node
/sys/devices/platform/soc/f4000000.pcie/pci0000:00/0000:00:00.0/of_node
/sys/devices/platform/soc/f4000000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:07.0/of_node
/sys/devices/platform/soc/f4000000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:07.0/pci_bus/0000:06/of_node
/sys/devices/platform/soc/f4000000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/pci_bus/0000:02/of_node
/sys/devices/platform/soc/f4000000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:05.0/of_node
/sys/devices/platform/soc/f4000000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:05.0/pci_bus/0000:05/of_node
/sys/devices/platform/soc/f4000000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:01.0/of_node
/sys/devices/platform/soc/f4000000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:01.0/pci_bus/0000:03/of_node
/sys/devices/platform/soc/f4000000.pcie/pci0000:00/0000:00:00.0/pci_bus/0000:01/of_node
/sys/devices/platform/soc/f4000000.pcie/pci0000:00/pci_bus/0000:00/of_node

Adding some debug prints with such change will produce the following
output:

$ dmesg|grep of_node
[ 4.932405] (null): pci_set_bus_of_node: of_node: /soc/pcie@f4000000
[ 4.985916] pci 0000:00:00.0: pci_set_of_node: of_node: /soc/pcie@f4000000
[ 5.014190] pci_bus 0000:01: pci_set_bus_of_node: of_node: /soc/pcie@f4000000/pcie@0,0
[ 5.065680] pci 0000:01:00.0: pci_set_of_node: of_node: /soc/pcie@f4000000/pcie@0,0
[ 5.118754] pci_bus 0000:02: pci_set_bus_of_node: use of_node of the parent
[ 5.135279] pci_bus 0000:02: pci_set_bus_of_node: of_node: /soc/pcie@f4000000/pcie@0,0
[ 5.158921] pci 0000:02:01.0: pci_set_of_node: of_node: /soc/pcie@f4000000/pcie@0,0
[ 5.187393] pci 0000:02:04.0: pci_set_of_node: of_node: /soc/pcie@f4000000/pcie@0,0
[ 5.215982] pci 0000:02:05.0: pci_set_of_node: of_node: /soc/pcie@f4000000/pcie@0,0
[ 5.244607] pci 0000:02:07.0: pci_set_of_node: of_node: /soc/pcie@f4000000/pcie@0,0
[ 5.272825] pci 0000:02:09.0: pci_set_of_node: of_node: /soc/pcie@f4000000/pcie@0,0
[ 5.335258] pci_bus 0000:03: pci_set_bus_of_node: of_node: /soc/pcie@f4000000/pcie@0,0/pcie@1,0
[ 5.367538] pci 0000:03:00.0: pci_set_of_node: of_node: /soc/pcie@f4000000/pcie@0,0/pcie@1,0
[ 5.415959] pci_bus 0000:04: pci_set_bus_of_node: use of_node of the parent
[ 5.424190] pci_bus 0000:04: pci_set_bus_of_node: of_node: (null)
[ 5.438727] pci_bus 0000:05: pci_set_bus_of_node: of_node: /soc/pcie@f4000000/pcie@0,0/pcie@5,0
[ 5.455691] pci_bus 0000:06: pci_set_bus_of_node: of_node: /soc/pcie@f4000000/pcie@0,0/pcie@7,0
[ 5.491643] pci 0000:06:00.0: pci_set_of_node: of_node: /soc/pcie@f4000000/pcie@0,0/pcie@7,0
[ 5.526157] pci_bus 0000:07: pci_set_bus_of_node: use of_node of the parent
[ 5.534361] pci_bus 0000:07: pci_set_bus_of_node: of_node: (null)

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@xxxxxxxxxx>
---
drivers/pci/of.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index a143b02b2dcd..b6fa3bd46ae6 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -41,6 +41,8 @@ void pci_set_bus_of_node(struct pci_bus *bus)
node = pcibios_get_phb_of_node(bus);
} else {
node = of_node_get(bus->self->dev.of_node);
+ if (!node)
+ node = of_node_get(bus->self->dev.parent->of_node);
if (node && of_property_read_bool(node, "external-facing"))
bus->self->external_facing = true;
}
--
2.31.1