PCI: Allow relaxed bridge window tail sizing for optional resources
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Mon, 16 Dec 2024 17:56:11 +0000 (19:56 +0200)
committerBjorn Helgaas <bhelgaas@google.com>
Tue, 18 Feb 2025 21:40:52 +0000 (15:40 -0600)
Commit 566f1dd52816 ("PCI: Relax bridge window tail sizing rules")
relaxed the bridge window requirements for non-optional size (size0)
but pbus_size_mem() also handles optional sizes (IOV resources) using
size1. This can manifest, e.g., as a failure to resize a BAR back to
its original size after it was first shrunk when device has a VF BAR
resource because the bridge window (size1) is enlarged beyond what is
strictly required to fit the downstream resources.

Allow using relaxed bridge window tail sizing rules also with the optional
resources (size1) so that the remove/realloc cycle during BAR resize
(smaller and back to the original size) does not fail unexpectedly due to
increase in bridge window size demand.

Also move add_align calculation to more logical place next to size1
assignment as they are strongly related to each other.

Link: https://lore.kernel.org/r/20241216175632.4175-5-ilpo.jarvinen@linux.intel.com
Fixes: 566f1dd52816 ("PCI: Relax bridge window tail sizing rules")
Reported-by: Michał Winiarski <michal.winiarski@intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Xiaochun Lee <lixc17@lenovo.com>
drivers/pci/setup-bus.c

index fd78606526ec1f556640365932871ec0ecb4b618..447f3aa1037c74c2942e75ae4e5ba6eb8fac24f3 100644 (file)
@@ -1146,7 +1146,6 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
        min_align = calculate_mem_align(aligns, max_order);
        min_align = max(min_align, win_align);
        size0 = calculate_memsize(size, min_size, 0, 0, resource_size(b_res), min_align);
-       add_align = max(min_align, add_align);
 
        if (bus->self && size0 &&
            !pbus_upstream_space_available(bus, mask | IORESOURCE_PREFETCH, type,
@@ -1159,8 +1158,21 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
        }
 
        if (realloc_head && (add_size > 0 || children_add_size > 0)) {
+               add_align = max(min_align, add_align);
                size1 = calculate_memsize(size, min_size, add_size, children_add_size,
                                          resource_size(b_res), add_align);
+
+               if (bus->self && size1 &&
+                   !pbus_upstream_space_available(bus, mask | IORESOURCE_PREFETCH, type,
+                                                  size1, add_align)) {
+                       min_align = 1ULL << (max_order + __ffs(SZ_1M));
+                       min_align = max(min_align, win_align);
+                       size1 = calculate_memsize(size, min_size, add_size, children_add_size,
+                                                 resource_size(b_res), win_align);
+                       pci_info(bus->self,
+                                "bridge window %pR to %pR requires relaxed alignment rules\n",
+                                b_res, &bus->busn_res);
+               }
        }
 
        if (!size0 && !size1) {