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: Rewrite bridge window head alignment function

The calculation of bridge window head alignment is done by
calculate_mem_align() [*]. With the default bridge window alignment, it
is used for both head and tail alignment.

The selected head alignment does not always result in tight-fitting
resources (gap at d4f00000-d4ffffff):

d4800000-dbffffff : PCI Bus 0000:06
d4800000-d48fffff : PCI Bus 0000:07
d4800000-d4803fff : 0000:07:00.0
d4800000-d4803fff : nvme
d4900000-d49fffff : PCI Bus 0000:0a
d4900000-d490ffff : 0000:0a:00.0
d4900000-d490ffff : r8169
d4910000-d4913fff : 0000:0a:00.0
d4a00000-d4cfffff : PCI Bus 0000:0b
d4a00000-d4bfffff : 0000:0b:00.0
d4a00000-d4bfffff : 0000:0b:00.0
d4c00000-d4c07fff : 0000:0b:00.0
d4d00000-d4dfffff : PCI Bus 0000:15
d4d00000-d4d07fff : 0000:15:00.0
d4d00000-d4d07fff : xhci-hcd
d4e00000-d4efffff : PCI Bus 0000:16
d4e00000-d4e7ffff : 0000:16:00.0
d4e80000-d4e803ff : 0000:16:00.0
d4e80000-d4e803ff : ahci
d5000000-dbffffff : PCI Bus 0000:0c

This has not caused problems (for years) with the default bridge window
tail alignment that grossly over-estimates the required tail alignment
leaving more tail room than necessary. With the introduction of relaxed
tail alignment that leaves no extra tail room whatsoever, any gaps will
immediately turn into assignment failures.

Introduce head alignment calculation that ensures no gaps are left and
apply the new approach when using relaxed alignment. We may want to
consider using it for the normal alignment eventually, but as the first
step, solve only the problem with the relaxed tail alignment.

([*] I don't understand the algorithm in calculate_mem_align().)

Link: https://git.kernel.org/history/history/c/5d0a8965aea9 ("[PATCH] 2.5.14: New PCI allocation code (alpha, arm, parisc) [2/2]")
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220775
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-3-ilpo.jarvinen@linux.intel.com

authored by

Ilpo Järvinen and committed by
Bjorn Helgaas
bc75c8e5 7e90360e

+44 -9
+44 -9
drivers/pci/setup-bus.c
··· 1228 1228 return min_align; 1229 1229 } 1230 1230 1231 + /* 1232 + * Calculate bridge window head alignment that leaves no gaps in between 1233 + * resources. 1234 + */ 1235 + static resource_size_t calculate_head_align(resource_size_t *aligns, 1236 + int max_order) 1237 + { 1238 + resource_size_t head_align = 1; 1239 + resource_size_t remainder = 0; 1240 + int order; 1241 + 1242 + /* Take the largest alignment as the starting point. */ 1243 + head_align <<= max_order + __ffs(SZ_1M); 1244 + 1245 + for (order = max_order - 1; order >= 0; order--) { 1246 + resource_size_t align1 = 1; 1247 + 1248 + align1 <<= order + __ffs(SZ_1M); 1249 + 1250 + /* 1251 + * Account smaller resources with alignment < max_order that 1252 + * could be used to fill head room if alignment less than 1253 + * max_order is used. 1254 + */ 1255 + remainder += aligns[order]; 1256 + 1257 + /* 1258 + * Test if head fill is enough to satisfy the alignment of 1259 + * the larger resources after reducing the alignment. 1260 + */ 1261 + while ((head_align > align1) && (remainder >= head_align / 2)) { 1262 + head_align /= 2; 1263 + remainder -= head_align; 1264 + } 1265 + } 1266 + 1267 + return head_align; 1268 + } 1269 + 1231 1270 /** 1232 1271 * pbus_upstream_space_available - Check no upstream resource limits allocation 1233 1272 * @bus: The bus ··· 1354 1315 { 1355 1316 struct pci_dev *dev; 1356 1317 resource_size_t min_align, win_align, align, size, size0, size1 = 0; 1357 - resource_size_t aligns[28]; /* Alignments from 1MB to 128TB */ 1318 + resource_size_t aligns[28] = {}; /* Alignments from 1MB to 128TB */ 1319 + resource_size_t aligns2[28] = {};/* Alignments from 1MB to 128TB */ 1358 1320 int order, max_order; 1359 1321 struct resource *b_res = pbus_select_window_for_type(bus, type); 1360 1322 resource_size_t children_add_size = 0; 1361 1323 resource_size_t children_add_align = 0; 1362 1324 resource_size_t add_align = 0; 1363 - resource_size_t relaxed_align; 1364 1325 resource_size_t old_size; 1365 1326 1366 1327 if (!b_res) ··· 1370 1331 if (b_res->parent) 1371 1332 return; 1372 1333 1373 - memset(aligns, 0, sizeof(aligns)); 1374 1334 max_order = 0; 1375 1335 size = 0; 1376 1336 ··· 1420 1382 */ 1421 1383 if (r_size <= align) 1422 1384 aligns[order] += align; 1385 + aligns2[order] += align; 1423 1386 if (order > max_order) 1424 1387 max_order = order; 1425 1388 ··· 1445 1406 1446 1407 if (bus->self && size0 && 1447 1408 !pbus_upstream_space_available(bus, b_res, size0, min_align)) { 1448 - relaxed_align = 1ULL << (max_order + __ffs(SZ_1M)); 1449 - relaxed_align = max(relaxed_align, win_align); 1450 - min_align = min(min_align, relaxed_align); 1409 + min_align = calculate_head_align(aligns2, max_order); 1451 1410 size0 = calculate_memsize(size, min_size, 0, 0, old_size, win_align); 1452 1411 resource_set_range(b_res, min_align, size0); 1453 1412 pci_info(bus->self, "bridge window %pR to %pR requires relaxed alignment rules\n", ··· 1459 1422 1460 1423 if (bus->self && size1 && 1461 1424 !pbus_upstream_space_available(bus, b_res, size1, add_align)) { 1462 - relaxed_align = 1ULL << (max_order + __ffs(SZ_1M)); 1463 - relaxed_align = max(relaxed_align, win_align); 1464 - min_align = min(min_align, relaxed_align); 1425 + min_align = calculate_head_align(aligns2, max_order); 1465 1426 size1 = calculate_memsize(size, min_size, add_size, children_add_size, 1466 1427 old_size, win_align); 1467 1428 pci_info(bus->self,