Revert "PCI: Remove from bus_list and release resources in pci_release_dev()"
Revert commitef83b0781a
"PCI: Remove from bus_list and release resources in pci_release_dev()" that made some nasty race conditions become possible. For example, if a Thunderbolt link is unplugged and then replugged immediately, the pci_release_dev() resulting from the hot-remove code path may be racing with the hot-add code path which after that commit causes various kinds of breakage to happen (up to and including a hard crash of the whole system). Moreover, the problem that commitef83b0781a
attempted to address cannot happen any more after commit8a4c5c329d
"PCI: Check parent kobject in pci_destroy_dev()", because pci_destroy_dev() will now return immediately if it has already been executed for the given device. Note, however, that the invocation of msi_remove_pci_irq_vectors() removed by commitef83b0781a
from pci_free_resources() along with the other changes made by it is not added back because of subsequent code changes depending on that modification. Fixes:ef83b0781a
(PCI: Remove from bus_list and release resources in pci_release_dev()) Reported-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
8a1f006ad3
commit
04480094de
|
@ -1208,18 +1208,6 @@ static void pci_release_capabilities(struct pci_dev *dev)
|
|||
pci_free_cap_save_buffers(dev);
|
||||
}
|
||||
|
||||
static void pci_free_resources(struct pci_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
pci_cleanup_rom(dev);
|
||||
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
|
||||
struct resource *res = dev->resource + i;
|
||||
if (res->parent)
|
||||
release_resource(res);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_release_dev - free a pci device structure when all users of it are finished.
|
||||
* @dev: device that's been disconnected
|
||||
|
@ -1229,14 +1217,9 @@ static void pci_free_resources(struct pci_dev *dev)
|
|||
*/
|
||||
static void pci_release_dev(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||
|
||||
down_write(&pci_bus_sem);
|
||||
list_del(&pci_dev->bus_list);
|
||||
up_write(&pci_bus_sem);
|
||||
|
||||
pci_free_resources(pci_dev);
|
||||
struct pci_dev *pci_dev;
|
||||
|
||||
pci_dev = to_pci_dev(dev);
|
||||
pci_release_capabilities(pci_dev);
|
||||
pci_release_of_node(pci_dev);
|
||||
pcibios_release_device(pci_dev);
|
||||
|
|
|
@ -3,6 +3,18 @@
|
|||
#include <linux/pci-aspm.h>
|
||||
#include "pci.h"
|
||||
|
||||
static void pci_free_resources(struct pci_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
pci_cleanup_rom(dev);
|
||||
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
|
||||
struct resource *res = dev->resource + i;
|
||||
if (res->parent)
|
||||
release_resource(res);
|
||||
}
|
||||
}
|
||||
|
||||
static void pci_stop_dev(struct pci_dev *dev)
|
||||
{
|
||||
pci_pme_active(dev, false);
|
||||
|
@ -25,6 +37,11 @@ static void pci_destroy_dev(struct pci_dev *dev)
|
|||
|
||||
device_del(&dev->dev);
|
||||
|
||||
down_write(&pci_bus_sem);
|
||||
list_del(&dev->bus_list);
|
||||
up_write(&pci_bus_sem);
|
||||
|
||||
pci_free_resources(dev);
|
||||
put_device(&dev->dev);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue