diff options
-rw-r--r-- | drivers/pci/pci.c | 26 |
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 | } |
4317 | EXPORT_SYMBOL_GPL(pci_try_reset_function); | 4323 | EXPORT_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 | } |