Message ID | 7339fd73ccaf58552737ab10008333fd9f7723f2.camel@kernel.crashing.org (mailing list archive) |
---|---|
State | Mainlined, archived |
Commit | fb794a708a71d7c6af55f04cc4ed2d5823fb8b33 |
Headers | show |
Series | [v2] PCI: Protect pci_reassign_bridge_resources() against concurrent addition/removal | expand |
On Wed, Sep 25, 2019 at 11:16:55AM +1000, Benjamin Herrenschmidt wrote: > pci_reassign_bridge_resources() can be called by pci_resize_resource() > at runtime. > > It will walk the PCI tree up and down, and isn't currently protected > against any changes or hotplug operation. > > Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Applied to pci/resource for v5.5, thanks! > --- > > v2: Fix a missing exit case > Reported by: Dan Carpenter <dan.carpenter@oracle.com> > > --- > drivers/pci/setup-bus.c | 8 +++++++- > 1 file changed, 7 insertions(+), 1 deletion(-) > > diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c > index 79b1fa6519be..871dad7d02ea 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 @@ 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; > } > >
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 79b1fa6519be..871dad7d02ea 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 @@ 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; }
pci_reassign_bridge_resources() can be called by pci_resize_resource() at runtime. It will walk the PCI tree up and down, and isn't currently protected against any changes or hotplug operation. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- v2: Fix a missing exit case Reported by: Dan Carpenter <dan.carpenter@oracle.com> --- drivers/pci/setup-bus.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)