Skip to content

Commit 0448009

Browse files
rafaeljwtorvalds
authored andcommitted
Revert "PCI: Remove from bus_list and release resources in pci_release_dev()"
Revert commit ef83b07 "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 commit ef83b07 attempted to address cannot happen any more after commit 8a4c5c3 "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 commit ef83b07 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: ef83b07 (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>
1 parent 8a1f006 commit 0448009

File tree

2 files changed

+19
-19
lines changed

2 files changed

+19
-19
lines changed

drivers/pci/probe.c

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,18 +1208,6 @@ static void pci_release_capabilities(struct pci_dev *dev)
12081208
pci_free_cap_save_buffers(dev);
12091209
}
12101210

1211-
static void pci_free_resources(struct pci_dev *dev)
1212-
{
1213-
int i;
1214-
1215-
pci_cleanup_rom(dev);
1216-
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1217-
struct resource *res = dev->resource + i;
1218-
if (res->parent)
1219-
release_resource(res);
1220-
}
1221-
}
1222-
12231211
/**
12241212
* pci_release_dev - free a pci device structure when all users of it are finished.
12251213
* @dev: device that's been disconnected
@@ -1229,14 +1217,9 @@ static void pci_free_resources(struct pci_dev *dev)
12291217
*/
12301218
static void pci_release_dev(struct device *dev)
12311219
{
1232-
struct pci_dev *pci_dev = to_pci_dev(dev);
1233-
1234-
down_write(&pci_bus_sem);
1235-
list_del(&pci_dev->bus_list);
1236-
up_write(&pci_bus_sem);
1237-
1238-
pci_free_resources(pci_dev);
1220+
struct pci_dev *pci_dev;
12391221

1222+
pci_dev = to_pci_dev(dev);
12401223
pci_release_capabilities(pci_dev);
12411224
pci_release_of_node(pci_dev);
12421225
pcibios_release_device(pci_dev);

drivers/pci/remove.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33
#include <linux/pci-aspm.h>
44
#include "pci.h"
55

6+
static void pci_free_resources(struct pci_dev *dev)
7+
{
8+
int i;
9+
10+
pci_cleanup_rom(dev);
11+
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
12+
struct resource *res = dev->resource + i;
13+
if (res->parent)
14+
release_resource(res);
15+
}
16+
}
17+
618
static void pci_stop_dev(struct pci_dev *dev)
719
{
820
pci_pme_active(dev, false);
@@ -25,6 +37,11 @@ static void pci_destroy_dev(struct pci_dev *dev)
2537

2638
device_del(&dev->dev);
2739

40+
down_write(&pci_bus_sem);
41+
list_del(&dev->bus_list);
42+
up_write(&pci_bus_sem);
43+
44+
pci_free_resources(dev);
2845
put_device(&dev->dev);
2946
}
3047

0 commit comments

Comments
 (0)