PCI: Align extra resources for hotplug bridges properly
authorMika Westerberg <mika.westerberg@linux.intel.com>
Tue, 31 Jan 2023 09:24:03 +0000 (11:24 +0200)
committerBjorn Helgaas <bhelgaas@google.com>
Tue, 7 Feb 2023 16:54:40 +0000 (10:54 -0600)
After division the extra resource space per hotplug bridge may not be
aligned according to the window alignment, so align it before passing it
down for further distribution.

Link: https://lore.kernel.org/r/20230131092405.29121-2-mika.westerberg@linux.intel.com
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/setup-bus.c

index b4096598dbcbb9e3aee7079258fd6bc7e06a9450..e440f264accb8a6ab47fc68af4cdeccc71bff164 100644 (file)
@@ -1891,6 +1891,7 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
         * resource space between hotplug bridges.
         */
        for_each_pci_bridge(dev, bus) {
+               struct resource *res;
                struct pci_bus *b;
 
                b = dev->subordinate;
@@ -1902,16 +1903,28 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
                 * hotplug-capable downstream ports taking alignment into
                 * account.
                 */
-               io.end = io.start + io_per_hp - 1;
-               mmio.end = mmio.start + mmio_per_hp - 1;
-               mmio_pref.end = mmio_pref.start + mmio_pref_per_hp - 1;
+               res = &dev->resource[PCI_BRIDGE_IO_WINDOW];
+               align = pci_resource_alignment(dev, res);
+               io.end = align ? io.start + ALIGN_DOWN(io_per_hp, align) - 1
+                              : io.start + io_per_hp - 1;
+
+               res = &dev->resource[PCI_BRIDGE_MEM_WINDOW];
+               align = pci_resource_alignment(dev, res);
+               mmio.end = align ? mmio.start + ALIGN_DOWN(mmio_per_hp, align) - 1
+                                : mmio.start + mmio_per_hp - 1;
+
+               res = &dev->resource[PCI_BRIDGE_PREF_MEM_WINDOW];
+               align = pci_resource_alignment(dev, res);
+               mmio_pref.end = align ? mmio_pref.start +
+                                       ALIGN_DOWN(mmio_pref_per_hp, align) - 1
+                                     : mmio_pref.start + mmio_pref_per_hp - 1;
 
                pci_bus_distribute_available_resources(b, add_list, io, mmio,
                                                       mmio_pref);
 
-               io.start += io_per_hp;
-               mmio.start += mmio_per_hp;
-               mmio_pref.start += mmio_pref_per_hp;
+               io.start += io.end + 1;
+               mmio.start += mmio.end + 1;
+               mmio_pref.start += mmio_pref.end + 1;
        }
 }