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: Add pbus_mem_size_optional() to handle optional sizes

The resource loop in pbus_size_mem() handles optional resources that are
either fully optional (SR-IOV and disabled Expansion ROMs) or bridge
windows that may be optional only for a part. The logic is a little
inconsistent when it comes to a bridge window that has only optional
children resources as it would be more natural to treat it similar to any
fully optional resource. As resource size should be zero in that case, it
shouldn't cause any bugs but it still seems useful to address the
inconsistency.

Place the optional size related code of pbus_size_mem() into
pbus_mem_size_optional() and add a check in pci_resource_is_optional()
for entirely optional bridge windows. Reorder the logic inside
pbus_mem_size_optional() such that fully optional resources are handled
the same irrespective of whether the resource is a bridge window or
not.

Additional motivation for this are the upcoming changes that add complexity
to the optional sizing logic due to Resizable BAR awareness. The extra
logic would exceed any reasonable indentation level if the optional sizing
code is kept within the loop body.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20251219174036.16738-14-ilpo.jarvinen@linux.intel.com

authored by

Ilpo Järvinen and committed by
Bjorn Helgaas
6a5e64c7 c10fe0c0

+54 -23
+54 -23
drivers/pci/setup-bus.c
··· 125 125 return dev_res ? dev_res->add_size : 0; 126 126 } 127 127 128 - static resource_size_t get_res_add_align(struct list_head *head, 129 - struct resource *res) 130 - { 131 - struct pci_dev_resource *dev_res; 132 - 133 - dev_res = res_to_dev_res(head, res); 134 - return dev_res ? dev_res->min_align : 0; 135 - } 136 - 137 128 static void restore_dev_resource(struct pci_dev_resource *dev_res) 138 129 { 139 130 struct resource *res = dev_res->res; ··· 376 385 if (pci_resource_is_iov(resno)) 377 386 return true; 378 387 if (resno == PCI_ROM_RESOURCE && !(res->flags & IORESOURCE_ROM_ENABLE)) 388 + return true; 389 + if (pci_resource_is_bridge_win(resno) && !resource_size(res)) 379 390 return true; 380 391 381 392 return false; ··· 1251 1258 return head_align; 1252 1259 } 1253 1260 1261 + /* 1262 + * pbus_size_mem_optional - Account optional resources in bridge window 1263 + * 1264 + * Account an optional resource or the optional part of the resource in bridge 1265 + * window size. 1266 + * 1267 + * Return: %true if the resource is entirely optional. 1268 + */ 1269 + static bool pbus_size_mem_optional(struct pci_dev *dev, int resno, 1270 + resource_size_t align, 1271 + struct list_head *realloc_head, 1272 + resource_size_t *add_align, 1273 + resource_size_t *children_add_size) 1274 + { 1275 + struct resource *res = pci_resource_n(dev, resno); 1276 + bool optional = pci_resource_is_optional(dev, resno); 1277 + resource_size_t r_size = resource_size(res); 1278 + struct pci_dev_resource *dev_res; 1279 + 1280 + if (!realloc_head) 1281 + return false; 1282 + 1283 + if (!optional) { 1284 + /* 1285 + * Only bridges have optional sizes in realloc_head at this 1286 + * point. As res_to_dev_res() walks the entire realloc_head 1287 + * list, skip calling it when known unnecessary. 1288 + */ 1289 + if (!pci_resource_is_bridge_win(resno)) 1290 + return false; 1291 + 1292 + dev_res = res_to_dev_res(realloc_head, res); 1293 + if (dev_res) { 1294 + *children_add_size += dev_res->add_size; 1295 + *add_align = max(*add_align, dev_res->min_align); 1296 + } 1297 + 1298 + return false; 1299 + } 1300 + 1301 + /* Put SRIOV requested res to the optional list */ 1302 + add_to_list(realloc_head, dev, res, 0, align); 1303 + *children_add_size += r_size; 1304 + *add_align = max(align, *add_align); 1305 + 1306 + return true; 1307 + } 1308 + 1254 1309 /** 1255 1310 * pbus_size_mem() - Size the memory window of a given bus 1256 1311 * ··· 1325 1284 resource_size_t aligns[28] = {}; /* Alignments from 1MB to 128TB */ 1326 1285 int order, max_order; 1327 1286 resource_size_t children_add_size = 0; 1328 - resource_size_t children_add_align = 0; 1329 1287 resource_size_t add_align = 0; 1330 1288 1331 1289 if (!b_res) ··· 1351 1311 if (b_res != pbus_select_window(bus, r)) 1352 1312 continue; 1353 1313 1354 - r_size = resource_size(r); 1355 1314 align = pci_resource_alignment(dev, r); 1356 1315 /* 1357 1316 * aligns[0] is for 1MB (since bridge memory ··· 1366 1327 continue; 1367 1328 } 1368 1329 1369 - /* Put SRIOV requested res to the optional list */ 1370 - if (realloc_head && pci_resource_is_optional(dev, i)) { 1371 - add_align = max(align, add_align); 1372 - add_to_list(realloc_head, dev, r, 0, 0 /* Don't care */); 1373 - children_add_size += r_size; 1330 + if (pbus_size_mem_optional(dev, i, align, 1331 + realloc_head, &add_align, 1332 + &children_add_size)) 1374 1333 continue; 1375 - } 1376 1334 1335 + r_size = resource_size(r); 1377 1336 size += max(r_size, align); 1378 1337 1379 1338 aligns[order] += align; 1380 1339 if (order > max_order) 1381 1340 max_order = order; 1382 - 1383 - if (realloc_head) { 1384 - children_add_size += get_res_add_size(realloc_head, r); 1385 - children_add_align = get_res_add_align(realloc_head, r); 1386 - add_align = max(add_align, children_add_align); 1387 - } 1388 1341 } 1389 1342 } 1390 1343