mirror of
https://github.com/torvalds/linux.git
synced 2026-01-24 23:16:46 +00:00
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:
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user