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: Account fully optional bridge windows correctly

pbus_size_mem_optional() adds dev_res->add_size of a bridge window into
children_add_size when the window has a non-optional part. However, if the
bridge window is fully optional, only r_size is added (which is zero for
such a window).

Also, a second dev_res entry will be added by pci_dev_res_add_to_list()
into realloc_head for the bridge window (resulting in triggering the
realloc_head-must-be-fully-consumed sanity check after a single pass of the
resource assignment algorithm):

WARNING: drivers/pci/setup-bus.c:2153 at pci_assign_unassigned_root_bus_resources+0xa5/0x260

Correct these problems by always adding dev_res->add_size for bridge
windows and not calling pci_dev_res_add_to_list() if the dev_res entry
exists.

Fixes: 6a5e64c75e82 ("PCI: Add pbus_mem_size_optional() to handle optional sizes")
Reported-by: RavitejaX Veesam <ravitejax.veesam@intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: RavitejaX Veesam <ravitejax.veesam@intel.com>
Link: https://patch.msgid.link/20260218223419.22366-1-ilpo.jarvinen@linux.intel.com

authored by

Ilpo Järvinen and committed by
Bjorn Helgaas
a3b93b42 e5f72cb9

+17 -14
+17 -14
drivers/pci/setup-bus.c
··· 1224 1224 struct resource *res = pci_resource_n(dev, resno); 1225 1225 bool optional = pci_resource_is_optional(dev, resno); 1226 1226 resource_size_t r_size = resource_size(res); 1227 - struct pci_dev_resource *dev_res; 1227 + struct pci_dev_resource *dev_res = NULL; 1228 1228 1229 1229 if (!realloc_head) 1230 1230 return false; 1231 1231 1232 - if (!optional) { 1233 - /* 1234 - * Only bridges have optional sizes in realloc_head at this 1235 - * point. As res_to_dev_res() walks the entire realloc_head 1236 - * list, skip calling it when known unnecessary. 1237 - */ 1238 - if (!pci_resource_is_bridge_win(resno)) 1239 - return false; 1240 - 1232 + /* 1233 + * Only bridges have optional sizes in realloc_head at this 1234 + * point. As res_to_dev_res() walks the entire realloc_head 1235 + * list, skip calling it when known unnecessary. 1236 + */ 1237 + if (pci_resource_is_bridge_win(resno)) { 1241 1238 dev_res = res_to_dev_res(realloc_head, res); 1242 1239 if (dev_res) { 1243 1240 *children_add_size += dev_res->add_size; 1244 1241 *add_align = max(*add_align, dev_res->min_align); 1245 1242 } 1246 - 1247 - return false; 1248 1243 } 1249 1244 1250 - /* Put SRIOV requested res to the optional list */ 1251 - pci_dev_res_add_to_list(realloc_head, dev, res, 0, align); 1245 + if (!optional) 1246 + return false; 1247 + 1248 + /* 1249 + * Put requested res to the optional list if not there yet (SR-IOV, 1250 + * disabled ROM). Bridge windows with an optional part are already 1251 + * on the list. 1252 + */ 1253 + if (!dev_res) 1254 + pci_dev_res_add_to_list(realloc_head, dev, res, 0, align); 1252 1255 *children_add_size += r_size; 1253 1256 *add_align = max(align, *add_align); 1254 1257