Skip to content

Commit 5bde837

Browse files
committed
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
2 parents 2a4d911 + 5528fd3 commit 5bde837

2 files changed

Lines changed: 20 additions & 21 deletions

File tree

drivers/pci/rebar.c

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,6 @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size,
295295
int exclude_bars)
296296
{
297297
struct pci_host_bridge *host;
298-
int old, ret;
299298

300299
/* Check if we must preserve the firmware's resource assignment */
301300
host = pci_find_host_bridge(dev->bus);
@@ -308,21 +307,6 @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size,
308307
if (!pci_rebar_size_supported(dev, resno, size))
309308
return -EINVAL;
310309

311-
old = pci_rebar_get_current_size(dev, resno);
312-
if (old < 0)
313-
return old;
314-
315-
ret = pci_rebar_set_size(dev, resno, size);
316-
if (ret)
317-
return ret;
318-
319-
ret = pci_do_resource_release_and_resize(dev, resno, size, exclude_bars);
320-
if (ret)
321-
goto error_resize;
322-
return 0;
323-
324-
error_resize:
325-
pci_rebar_set_size(dev, resno, old);
326-
return ret;
310+
return pci_do_resource_release_and_resize(dev, resno, size, exclude_bars);
327311
}
328312
EXPORT_SYMBOL(pci_resize_resource);

drivers/pci/setup-bus.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2504,12 +2504,20 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
25042504
struct resource *b_win, *r;
25052505
LIST_HEAD(saved);
25062506
unsigned int i;
2507-
int ret = 0;
2507+
int old, ret;
25082508

25092509
b_win = pbus_select_window(bus, res);
25102510
if (!b_win)
25112511
return -EINVAL;
25122512

2513+
old = pci_rebar_get_current_size(pdev, resno);
2514+
if (old < 0)
2515+
return old;
2516+
2517+
ret = pci_rebar_set_size(pdev, resno, size);
2518+
if (ret)
2519+
return ret;
2520+
25132521
pci_dev_for_each_resource(pdev, r, i) {
25142522
if (i >= PCI_BRIDGE_RESOURCES)
25152523
break;
@@ -2542,7 +2550,15 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
25422550
return ret;
25432551

25442552
restore:
2545-
/* Revert to the old configuration */
2553+
/*
2554+
* Revert to the old configuration.
2555+
*
2556+
* BAR Size must be restored first because it affects the read-only
2557+
* bits in BAR (the old address might not be restorable otherwise
2558+
* due to low address bits).
2559+
*/
2560+
pci_rebar_set_size(pdev, resno, old);
2561+
25462562
list_for_each_entry(dev_res, &saved, list) {
25472563
struct resource *res = dev_res->res;
25482564
struct pci_dev *dev = dev_res->dev;
@@ -2556,8 +2572,7 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
25562572

25572573
restore_dev_resource(dev_res);
25582574

2559-
ret = pci_claim_resource(dev, i);
2560-
if (ret)
2575+
if (pci_claim_resource(dev, i))
25612576
continue;
25622577

25632578
if (i < PCI_BRIDGE_RESOURCES) {

0 commit comments

Comments
 (0)