@@ -321,4 +321,20 @@ static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)
}
#endif
+#ifdef CONFIG_PCI_STATIC_ENUMERATION
+/**
+ * pci_bus_subordinate() - return the subordinate bus number assigned
+ * to @dev by the static enumeration profile, or 0 if not set
+ */
+static inline unsigned char pci_bus_subordinate(struct pci_bus *bus)
+{
+ return bus->subordinate;
+}
+#else
+static inline unsigned char pci_bus_subordinate(struct pci_bus *bus)
+{
+ return 0;
+}
+#endif
+
#endif /* DRIVERS_PCI_H */
@@ -867,8 +867,17 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
if (!child)
goto out;
pci_bus_insert_busn_res(child, child->number, 0xff);
+ /* child's subordinate bus will be calculated
+ during pass 2 */
}
+
+ /* if the child bus has a subordinate value set by a
+ static enumeration profile, then use that bus's
+ subordinate+1 as the next probed bus number */
+ if (max < pci_bus_subordinate(child))
+ max = pci_bus_subordinate(child);
max++;
+
buses = (buses & 0xff000000)
| ((unsigned int)(child->primary) << 0)
| ((unsigned int)(child->busn_res.start) << 8)
@@ -1863,6 +1872,13 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
}
/*
+ * Adjust max if this bus has a subordinate number specified
+ * by the static enumeration profile
+ */
+ if (max < pci_bus_subordinate(bus))
+ max = pci_bus_subordinate(bus);
+
+ /*
* We've scanned the bus and so we know all about what's on
* the other side of any bridges that may be on this bus plus
* any devices.
@@ -461,6 +461,9 @@ struct pci_bus {
#ifdef CONFIG_PCI_DOMAINS_GENERIC
int domain_nr;
#endif
+#ifdef CONFIG_PCI_STATIC_ENUMERATION
+ unsigned char subordinate; /* value set via static enumeration */
+#endif
char name[48];
This commit adds the subordinate field to struct pci_bus. Normally, the subordinate is automatically calculated while scanning children of the bus and counting the number of downstream buses. With static enumeration, a bus's subordinate may need to be greater than the count, such as when a PCI device is powered on after initial enumeration. Without the subordinate field, if the newly powered device is itself a bridge, then it will not have a valid secondary number without reshuffling all existing devices. By storing the bus's intended subordinate number, the scanning algorithm can skip over reserved numbers while enumerating devices. The value 0 means to use the existing enumerating algorithm. An upcoming commit will set that subordinate field to a non-zero value. Signed-off-by: Jason Tang <jason.tang2@ngc.com> --- drivers/pci/pci.h | 16 ++++++++++++++++ drivers/pci/probe.c | 16 ++++++++++++++++ include/linux/pci.h | 3 +++ 3 files changed, 35 insertions(+)