Commit fb794a70 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Bjorn Helgaas
Browse files

PCI: Protect pci_reassign_bridge_resources() against concurrent addition/removal

pci_reassign_bridge_resources() can be called by pci_resize_resource() at
runtime, it walks the PCI tree up and down, and it isn't currently
protected against any changes or hotplug operation.

Hold the pci_bus_sem to protect it.

Link: https://lore.kernel.org/r/7339fd73ccaf58552737ab10008333fd9f7723f2.camel@kernel.crashing.org


Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent 54ecb8f7
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -2066,6 +2066,8 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
	unsigned int i;
	int ret;

	down_read(&pci_bus_sem);

	/* Walk to the root hub, releasing bridge BARs when possible */
	next = bridge;
	do {
@@ -2100,8 +2102,10 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
		next = bridge->bus ? bridge->bus->self : NULL;
	} while (next);

	if (list_empty(&saved))
	if (list_empty(&saved)) {
		up_read(&pci_bus_sem);
		return -ENOENT;
	}

	__pci_bus_size_bridges(bridge->subordinate, &added);
	__pci_bridge_assign_resources(bridge, &added, &failed);
@@ -2122,6 +2126,7 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
	}

	free_list(&saved);
	up_read(&pci_bus_sem);
	return 0;

cleanup:
@@ -2150,6 +2155,7 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
		pci_setup_bridge(bridge->subordinate);
	}
	free_list(&saved);
	up_read(&pci_bus_sem);

	return ret;
}