diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2019-09-25 11:16:55 +1000 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2019-09-30 14:53:31 -0500 |
commit | fb794a708a71d7c6af55f04cc4ed2d5823fb8b33 (patch) | |
tree | 4343000cc3fd5f453cd8a6943330ad1a25840ccb | |
parent | 54ecb8f7028c5eb3d740bb82b0f1d90f2df63c5c (diff) |
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: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r-- | drivers/pci/setup-bus.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index e7dbe21705ba..f1c51943bdfc 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -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 @@ cleanup: pci_setup_bridge(bridge->subordinate); } free_list(&saved); + up_read(&pci_bus_sem); return ret; } |