Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

PCI: Fix bridge window alignment with optional resources

pbus_size_mem() has two alignments, one for required resources in min_align
and another in add_align that takes account optional resources.

The add_align is applied to the bridge window through the realloc_head
list. It can happen, however, that add_align is larger than min_align but
calculated size1 and size0 are equal due to extra tailroom (e.g., hotplug
reservation, tail alignment), and therefore no entry is created to the
realloc_head list. Without the bridge appearing in the realloc head,
add_align is lost when pbus_size_mem() returns.

The problem is visible in this log for 0000:05:00.0 which lacks
add_size ... add_align ... line that would indicate it was added into
the realloc_head list:

pci 0000:05:00.0: PCI bridge to [bus 06-16]
...
pci 0000:06:00.0: bridge window [mem 0x00100000-0x001fffff] to [bus 07] requires relaxed alignment rules
pci 0000:06:06.0: bridge window [mem 0x00100000-0x001fffff] to [bus 0a] requires relaxed alignment rules
pci 0000:06:07.0: bridge window [mem 0x00100000-0x003fffff] to [bus 0b] requires relaxed alignment rules
pci 0000:06:08.0: bridge window [mem 0x00800000-0x00ffffff 64bit pref] to [bus 0c-14] requires relaxed alignment rules
pci 0000:06:08.0: bridge window [mem 0x01000000-0x057fffff] to [bus 0c-14] requires relaxed alignment rules
pci 0000:06:08.0: bridge window [mem 0x01000000-0x057fffff] to [bus 0c-14] requires relaxed alignment rules
pci 0000:06:08.0: bridge window [mem 0x01000000-0x057fffff] to [bus 0c-14] add_size 100000 add_align 1000000
pci 0000:06:0c.0: bridge window [mem 0x00100000-0x001fffff] to [bus 15] requires relaxed alignment rules
pci 0000:06:0d.0: bridge window [mem 0x00100000-0x001fffff] to [bus 16] requires relaxed alignment rules
pci 0000:06:0d.0: bridge window [mem 0x00100000-0x001fffff] to [bus 16] requires relaxed alignment rules
pci 0000:05:00.0: bridge window [mem 0xd4800000-0xd97fffff]: assigned
pci 0000:05:00.0: bridge window [mem 0x1060000000-0x10607fffff 64bit pref]: assigned
pci 0000:06:08.0: bridge window [mem size 0x04900000]: can't assign; no space
pci 0000:06:08.0: bridge window [mem size 0x04900000]: failed to assign

While this bug itself seems old, it has likely become more visible after
the relaxed tail alignment that does not grossly overestimate the size
needed for the bridge window.

Make sure add_align > min_align too results in adding an entry into the
realloc head list. In addition, add handling to the cases where add_size is
zero while only alignment differs.

Fixes: d74b9027a4da ("PCI: Consider additional PF's IOV BAR alignment in sizing and assigning")
Reported-by: Malte Schröder <malte+lkml@tnxip.de>
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>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20251219174036.16738-2-ilpo.jarvinen@linux.intel.com

authored by

Ilpo Järvinen and committed by
Bjorn Helgaas
7e90360e 11721c45

+6 -4
+6 -4
drivers/pci/setup-bus.c
··· 14 14 * tighter packing. Prefetchable range support. 15 15 */ 16 16 17 + #include <linux/align.h> 17 18 #include <linux/bitops.h> 18 19 #include <linux/bug.h> 19 20 #include <linux/init.h> ··· 457 456 "%s %pR: ignoring failure in optional allocation\n", 458 457 res_name, res); 459 458 } 460 - } else if (add_size > 0) { 459 + } else if (add_size > 0 || !IS_ALIGNED(res->start, align)) { 461 460 res->flags |= add_res->flags & 462 461 (IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN); 463 462 if (pci_reassign_resource(dev, idx, add_size, align)) ··· 1443 1442 1444 1443 resource_set_range(b_res, min_align, size0); 1445 1444 b_res->flags |= IORESOURCE_STARTALIGN; 1446 - if (bus->self && size1 > size0 && realloc_head) { 1445 + if (bus->self && realloc_head && (size1 > size0 || add_align > min_align)) { 1447 1446 b_res->flags &= ~IORESOURCE_DISABLED; 1448 - add_to_list(realloc_head, bus->self, b_res, size1-size0, add_align); 1447 + add_size = size1 > size0 ? size1 - size0 : 0; 1448 + add_to_list(realloc_head, bus->self, b_res, add_size, add_align); 1449 1449 pci_info(bus->self, "bridge window %pR to %pR add_size %llx add_align %llx\n", 1450 1450 b_res, &bus->busn_res, 1451 - (unsigned long long) (size1 - size0), 1451 + (unsigned long long) add_size, 1452 1452 (unsigned long long) add_align); 1453 1453 } 1454 1454 }