[PATCH 1/1] PCI: Fix bus number allocation for switches with multiple downstream ports
From: Nicholas Johnson
Date: Tue Jun 23 2026 - 11:57:29 EST
When scanning a PCIe switch with multiple downstream ports, the kernel currently
fails to allocate bus numbers beyond the first downstream port.
The issue occurs in pci_scan_bridge_extend() when scanning an already configured
bridge in pass 1. The code updates 'max' using the old 'subordinate' value from
pass 0 instead of 'cmax', the actual subordinate bus number returned from
scanning the child bus. This causes the parent bridge to never advance past the
first downstream port.
Fix this by updating 'max' with 'cmax' instead of 'subordinate', ensuring the
parent bridge correctly tracks the bus numbers consumed by all its downstream
ports.
Without this fix, only the first downstream port of a switch is enumerated,
breaking Thunderbolt daisy chaining and other multi-port PCIe switch
configurations where bus numbers need to be allocated beyond the first port.
For example, on an Alienware 15 R4 with an Intel Core i9-8950HK, the built-in
JHL6340 Thunderbolt controller fails to enumerate beyond the first downstream
port during native OS enumeration, preventing proper Thunderbolt device tree
discovery and hotplug functionality.
Signed-off-by: Nicholas Johnson <nicholas.johnson-opensource@xxxxxxxxxxxxxx>
---
drivers/pci/probe.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index b63cd0c31..8fb09cbb6 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -3124,6 +3124,17 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus,
normal_bridges++;
}
+ /*
+ * Some host bridge scan paths pass available_buses == 0 even though
+ * the bus-number resource contains space reserved for descendants.
+ * Preserve that space when this bus has a hotplug-capable bridge so
+ * it can be distributed during the second bridge scan.
+ */
+ if (!available_buses && hotplug_bridges &&
+ bus->busn_res.end > bus->busn_res.start)
+ available_buses =
+ bus->busn_res.end - bus->busn_res.start;
+
/*
* Scan bridges that are already configured. We don't touch them
* unless they are misconfigured (which will be done in the second
--
2.53.0