| From 351bf52d2a7b4a7d41af3aa902b5d459f87ba29c Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 19 Dec 2025 19:40:16 +0200 |
| Subject: PCI: Stop over-estimating bridge window size |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> |
| |
| [ Upstream commit 3958bf16e2fe1b1c95467e58694102122c951a31 ] |
| |
| New way to calculate the bridge window head alignment produces tight-fit, |
| that is, it does not leave any gaps between the resources. Similarly, |
| relaxed tail alignment does not leave extra tail room. |
| |
| Start to use bridge window calculation that does not over-estimate the size |
| of the required window. |
| |
| pbus_upstream_space_available() can be removed. |
| |
| Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> |
| Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> |
| Tested-by: Malte Schröder <malte+lkml@tnxip.de> |
| Link: https://patch.msgid.link/20251219174036.16738-4-ilpo.jarvinen@linux.intel.com |
| Stable-dep-of: f909e3ee3ed1 ("PCI: Remove old_size limit from bridge window sizing") |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/pci/setup-bus.c | 97 +++-------------------------------------- |
| 1 file changed, 5 insertions(+), 92 deletions(-) |
| |
| diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c |
| index 99086980e102e..ed23778659114 100644 |
| --- a/drivers/pci/setup-bus.c |
| +++ b/drivers/pci/setup-bus.c |
| @@ -1266,68 +1266,6 @@ static resource_size_t calculate_head_align(resource_size_t *aligns, |
| return head_align; |
| } |
| |
| -/** |
| - * pbus_upstream_space_available - Check no upstream resource limits allocation |
| - * @bus: The bus |
| - * @res: The resource to help select the correct bridge window |
| - * @size: The size required from the bridge window |
| - * @align: Required alignment for the resource |
| - * |
| - * Check that @size can fit inside the upstream bridge resources that are |
| - * already assigned. Select the upstream bridge window based on the type of |
| - * @res. |
| - * |
| - * Return: %true if enough space is available on all assigned upstream |
| - * resources. |
| - */ |
| -static bool pbus_upstream_space_available(struct pci_bus *bus, |
| - struct resource *res, |
| - resource_size_t size, |
| - resource_size_t align) |
| -{ |
| - struct resource_constraint constraint = { |
| - .max = RESOURCE_SIZE_MAX, |
| - .align = align, |
| - }; |
| - struct pci_bus *downstream = bus; |
| - |
| - while ((bus = bus->parent)) { |
| - if (pci_is_root_bus(bus)) |
| - break; |
| - |
| - res = pbus_select_window(bus, res); |
| - if (!res) |
| - return false; |
| - if (!res->parent) |
| - continue; |
| - |
| - if (resource_size(res) >= size) { |
| - struct resource gap = {}; |
| - |
| - if (find_resource_space(res, &gap, size, &constraint) == 0) { |
| - gap.flags = res->flags; |
| - pci_dbg(bus->self, |
| - "Assigned bridge window %pR to %pR free space at %pR\n", |
| - res, &bus->busn_res, &gap); |
| - return true; |
| - } |
| - } |
| - |
| - if (bus->self) { |
| - pci_info(bus->self, |
| - "Assigned bridge window %pR to %pR cannot fit 0x%llx required for %s bridging to %pR\n", |
| - res, &bus->busn_res, |
| - (unsigned long long)size, |
| - pci_name(downstream->self), |
| - &downstream->busn_res); |
| - } |
| - |
| - return false; |
| - } |
| - |
| - return true; |
| -} |
| - |
| /** |
| * pbus_size_mem() - Size the memory window of a given bus |
| * |
| @@ -1354,7 +1292,6 @@ static void pbus_size_mem(struct pci_bus *bus, unsigned long type, |
| struct pci_dev *dev; |
| resource_size_t min_align, win_align, align, size, size0, size1 = 0; |
| resource_size_t aligns[28] = {}; /* Alignments from 1MB to 128TB */ |
| - resource_size_t aligns2[28] = {};/* Alignments from 1MB to 128TB */ |
| int order, max_order; |
| struct resource *b_res = pbus_select_window_for_type(bus, type); |
| resource_size_t children_add_size = 0; |
| @@ -1413,13 +1350,8 @@ static void pbus_size_mem(struct pci_bus *bus, unsigned long type, |
| continue; |
| } |
| size += max(r_size, align); |
| - /* |
| - * Exclude ranges with size > align from calculation of |
| - * the alignment. |
| - */ |
| - if (r_size <= align) |
| - aligns[order] += align; |
| - aligns2[order] += align; |
| + |
| + aligns[order] += align; |
| if (order > max_order) |
| max_order = order; |
| |
| @@ -1433,38 +1365,19 @@ static void pbus_size_mem(struct pci_bus *bus, unsigned long type, |
| |
| old_size = resource_size(b_res); |
| win_align = window_alignment(bus, b_res->flags); |
| - min_align = calculate_mem_align(aligns, max_order); |
| + min_align = calculate_head_align(aligns, max_order); |
| min_align = max(min_align, win_align); |
| - size0 = calculate_memsize(size, min_size, 0, 0, old_size, min_align); |
| + size0 = calculate_memsize(size, min_size, 0, 0, old_size, win_align); |
| |
| if (size0) { |
| resource_set_range(b_res, min_align, size0); |
| b_res->flags &= ~IORESOURCE_DISABLED; |
| } |
| |
| - if (bus->self && size0 && |
| - !pbus_upstream_space_available(bus, b_res, size0, min_align)) { |
| - min_align = calculate_head_align(aligns2, max_order); |
| - size0 = calculate_memsize(size, min_size, 0, 0, old_size, win_align); |
| - resource_set_range(b_res, min_align, size0); |
| - pci_info(bus->self, "bridge window %pR to %pR requires relaxed alignment rules\n", |
| - b_res, &bus->busn_res); |
| - } |
| - |
| 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, |
| - old_size, add_align); |
| - |
| - if (bus->self && size1 && |
| - !pbus_upstream_space_available(bus, b_res, size1, add_align)) { |
| - min_align = calculate_head_align(aligns2, max_order); |
| - size1 = calculate_memsize(size, min_size, add_size, children_add_size, |
| - old_size, win_align); |
| - pci_info(bus->self, |
| - "bridge window %pR to %pR requires relaxed alignment rules\n", |
| - b_res, &bus->busn_res); |
| - } |
| + old_size, win_align); |
| } |
| |
| if (!size0 && !size1) { |
| -- |
| 2.51.0 |
| |