aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/pci.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 3b38e98e68df..f4587f6f8739 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4143,6 +4143,12 @@ static void pci_reset_notify(struct pci_dev *dev, bool prepare)
4143{ 4143{
4144 const struct pci_error_handlers *err_handler = 4144 const struct pci_error_handlers *err_handler =
4145 dev->driver ? dev->driver->err_handler : NULL; 4145 dev->driver ? dev->driver->err_handler : NULL;
4146
4147 /*
4148 * dev->driver->err_handler->reset_notify() is protected against
4149 * races with ->remove() by the device lock, which must be held by
4150 * the caller.
4151 */
4146 if (err_handler && err_handler->reset_notify) 4152 if (err_handler && err_handler->reset_notify)
4147 err_handler->reset_notify(dev, prepare); 4153 err_handler->reset_notify(dev, prepare);
4148} 4154}
@@ -4278,11 +4284,13 @@ int pci_reset_function(struct pci_dev *dev)
4278 if (rc) 4284 if (rc)
4279 return rc; 4285 return rc;
4280 4286
4287 pci_dev_lock(dev);
4281 pci_dev_save_and_disable(dev); 4288 pci_dev_save_and_disable(dev);
4282 4289
4283 rc = pci_dev_reset(dev, 0); 4290 rc = __pci_dev_reset(dev, 0);
4284 4291
4285 pci_dev_restore(dev); 4292 pci_dev_restore(dev);
4293 pci_dev_unlock(dev);
4286 4294
4287 return rc; 4295 return rc;
4288} 4296}
@@ -4302,16 +4310,14 @@ int pci_try_reset_function(struct pci_dev *dev)
4302 if (rc) 4310 if (rc)
4303 return rc; 4311 return rc;
4304 4312
4305 pci_dev_save_and_disable(dev); 4313 if (!pci_dev_trylock(dev))
4314 return -EAGAIN;
4306 4315
4307 if (pci_dev_trylock(dev)) { 4316 pci_dev_save_and_disable(dev);
4308 rc = __pci_dev_reset(dev, 0); 4317 rc = __pci_dev_reset(dev, 0);
4309 pci_dev_unlock(dev); 4318 pci_dev_unlock(dev);
4310 } else
4311 rc = -EAGAIN;
4312 4319
4313 pci_dev_restore(dev); 4320 pci_dev_restore(dev);
4314
4315 return rc; 4321 return rc;
4316} 4322}
4317EXPORT_SYMBOL_GPL(pci_try_reset_function); 4323EXPORT_SYMBOL_GPL(pci_try_reset_function);
@@ -4461,7 +4467,9 @@ static void pci_bus_save_and_disable(struct pci_bus *bus)
4461 struct pci_dev *dev; 4467 struct pci_dev *dev;
4462 4468
4463 list_for_each_entry(dev, &bus->devices, bus_list) { 4469 list_for_each_entry(dev, &bus->devices, bus_list) {
4470 pci_dev_lock(dev);
4464 pci_dev_save_and_disable(dev); 4471 pci_dev_save_and_disable(dev);
4472 pci_dev_unlock(dev);
4465 if (dev->subordinate) 4473 if (dev->subordinate)
4466 pci_bus_save_and_disable(dev->subordinate); 4474 pci_bus_save_and_disable(dev->subordinate);
4467 } 4475 }
@@ -4476,7 +4484,9 @@ static void pci_bus_restore(struct pci_bus *bus)
4476 struct pci_dev *dev; 4484 struct pci_dev *dev;
4477 4485
4478 list_for_each_entry(dev, &bus->devices, bus_list) { 4486 list_for_each_entry(dev, &bus->devices, bus_list) {
4487 pci_dev_lock(dev);
4479 pci_dev_restore(dev); 4488 pci_dev_restore(dev);
4489 pci_dev_unlock(dev);
4480 if (dev->subordinate) 4490 if (dev->subordinate)
4481 pci_bus_restore(dev->subordinate); 4491 pci_bus_restore(dev->subordinate);
4482 } 4492 }