Commit 5bde8370 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 2a4d9114 5528fd38
Loading
Loading
Loading
Loading
+1 −17
Original line number Diff line number Diff line
@@ -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);
+19 −4
Original line number Diff line number Diff line
@@ -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 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
	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 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size

		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) {