From: Ilpo Järvinen ilpo.jarvinen@linux.intel.com
[ Upstream commit a43ac325c7cbbfe72bdf9178059b3ee9f5a2c7dd ]
Bridge windows are read twice from PCI Config Space, the first time from pci_read_bridge_windows(), which does not set up the device's resources. This causes problems down the road as child resources of the bridge cannot check whether they reside within the bridge window or not.
Set up the bridge windows already in pci_read_bridge_windows().
Signed-off-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Link: https://patch.msgid.link/20250924134228.1663-2-ilpo.jarvinen@linux.intel.com Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
YES - `pci_alloc_child_bus()` copies each subordinate bus window to `child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i]` before any child is scanned (`drivers/pci/probe.c:1245-1248`). Without this patch, those `bridge->resource[...]` entries are still zeroed; the first call to `pci_read_bridge_windows()` only logged with a stack-local `struct resource`. - Child drivers often probe immediately (device_add → bus_probe_device) while the bus scan is still in progress. During their `pci_enable_device()` they hit `pci_claim_resource()` (`drivers/pci/setup-res.c:154-169`), which calls `pci_find_parent_resource()` to make sure the BAR sits inside an upstream bridge window (`drivers/pci/pci.c:737-767`). Because `pcibios_fixup_bus()` (the point where `pci_read_bridge_bases()` re- reads the window into the real resource) runs only after the entire bus has been scanned (`drivers/pci/probe.c:3091-3106`), the parent window is still zero and the containment test fails. Result: `pci_enable_device()` reports “can't claim; no compatible bridge window” and the device never comes up behind that bridge. - The patch fixes that race by writing the values directly into the bridge’s real resources the first time we read config space (`drivers/pci/probe.c:540-588`). When the subordinate bus is created, the copied pointers already describe the real aperture, so drivers can claim their BARs successfully even if they probe before the later fixup. - Behavioural risk is negligible: we still populate the same resource structures with the same data, only earlier; the later `pci_read_bridge_bases()` call simply refreshes them with `log=false`. No new dependencies or behavioural changes outside this bug fix path, making it safe for stable.
Natural next step: consider tagging with a `Fixes` reference upstream to ease stable selection.
drivers/pci/probe.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a56dfa1c9b6ff..0b8c82c610baa 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -524,10 +524,14 @@ static void pci_read_bridge_windows(struct pci_dev *bridge) } if (io) { bridge->io_window = 1; - pci_read_bridge_io(bridge, &res, true); + pci_read_bridge_io(bridge, + pci_resource_n(bridge, PCI_BRIDGE_IO_WINDOW), + true); }
- pci_read_bridge_mmio(bridge, &res, true); + pci_read_bridge_mmio(bridge, + pci_resource_n(bridge, PCI_BRIDGE_MEM_WINDOW), + true);
/* * DECchip 21050 pass 2 errata: the bridge may miss an address @@ -565,7 +569,10 @@ static void pci_read_bridge_windows(struct pci_dev *bridge) bridge->pref_64_window = 1; }
- pci_read_bridge_mmio_pref(bridge, &res, true); + pci_read_bridge_mmio_pref(bridge, + pci_resource_n(bridge, + PCI_BRIDGE_PREF_MEM_WINDOW), + true); }
void pci_read_bridge_bases(struct pci_bus *child)