Merge tag 'pci-v6.19-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci

Pull PCI fixes from Bjorn Helgaas:

 - Fix the pci_do_resource_release_and_resize() failure path, which
   clobbered the intended failure return value (Ilpo Järvinen)

 - Restore resizable BAR size before value because the size determines
   which bits are writable; this fixes i915 and xe regressions (Ilpo
   Järvinen)

* tag 'pci-v6.19-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci:
  PCI: Fix Resizable BAR restore order
  PCI: Fix BAR resize rollback path overwriting ret
This commit is contained in:
Linus Torvalds
2026-01-23 13:20:24 -08:00
2 changed files with 20 additions and 21 deletions

View File

@@ -295,7 +295,6 @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size,
int exclude_bars)
{
struct pci_host_bridge *host;
int old, ret;
/* Check if we must preserve the firmware's resource assignment */
host = pci_find_host_bridge(dev->bus);
@@ -308,21 +307,6 @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size,
if (!pci_rebar_size_supported(dev, resno, size))
return -EINVAL;
old = pci_rebar_get_current_size(dev, resno);
if (old < 0)
return old;
ret = pci_rebar_set_size(dev, resno, size);
if (ret)
return ret;
ret = pci_do_resource_release_and_resize(dev, resno, size, exclude_bars);
if (ret)
goto error_resize;
return 0;
error_resize:
pci_rebar_set_size(dev, resno, old);
return ret;
return pci_do_resource_release_and_resize(dev, resno, size, exclude_bars);
}
EXPORT_SYMBOL(pci_resize_resource);

View File

@@ -2504,12 +2504,20 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
struct resource *b_win, *r;
LIST_HEAD(saved);
unsigned int i;
int ret = 0;
int old, ret;
b_win = pbus_select_window(bus, res);
if (!b_win)
return -EINVAL;
old = pci_rebar_get_current_size(pdev, resno);
if (old < 0)
return old;
ret = pci_rebar_set_size(pdev, resno, size);
if (ret)
return ret;
pci_dev_for_each_resource(pdev, r, i) {
if (i >= PCI_BRIDGE_RESOURCES)
break;
@@ -2542,7 +2550,15 @@ out:
return ret;
restore:
/* Revert to the old configuration */
/*
* Revert to the old configuration.
*
* BAR Size must be restored first because it affects the read-only
* bits in BAR (the old address might not be restorable otherwise
* due to low address bits).
*/
pci_rebar_set_size(pdev, resno, old);
list_for_each_entry(dev_res, &saved, list) {
struct resource *res = dev_res->res;
struct pci_dev *dev = dev_res->dev;
@@ -2556,8 +2572,7 @@ restore:
restore_dev_resource(dev_res);
ret = pci_claim_resource(dev, i);
if (ret)
if (pci_claim_resource(dev, i))
continue;
if (i < PCI_BRIDGE_RESOURCES) {