Commit 04480094de7242d08bb62088e713fd7fe00443b4
Committed by
Linus Torvalds
1 parent
8a1f006ad3
Exists in
master
and in
16 other branches
Revert "PCI: Remove from bus_list and release resources in pci_release_dev()"
Revert commit ef83b0781a73 "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 ef83b0781a73 attempted to address cannot happen any more after commit 8a4c5c329de7 "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 ef83b0781a73 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: ef83b0781a73 (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>
Showing 2 changed files with 19 additions and 19 deletions Side-by-side Diff
drivers/pci/probe.c
... | ... | @@ -1208,18 +1208,6 @@ |
1208 | 1208 | pci_free_cap_save_buffers(dev); |
1209 | 1209 | } |
1210 | 1210 | |
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 | - | |
1223 | 1211 | /** |
1224 | 1212 | * pci_release_dev - free a pci device structure when all users of it are finished. |
1225 | 1213 | * @dev: device that's been disconnected |
1226 | 1214 | |
... | ... | @@ -1229,14 +1217,9 @@ |
1229 | 1217 | */ |
1230 | 1218 | static void pci_release_dev(struct device *dev) |
1231 | 1219 | { |
1232 | - struct pci_dev *pci_dev = to_pci_dev(dev); | |
1220 | + struct pci_dev *pci_dev; | |
1233 | 1221 | |
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); | |
1239 | - | |
1222 | + pci_dev = to_pci_dev(dev); | |
1240 | 1223 | pci_release_capabilities(pci_dev); |
1241 | 1224 | pci_release_of_node(pci_dev); |
1242 | 1225 | pcibios_release_device(pci_dev); |
drivers/pci/remove.c
... | ... | @@ -3,6 +3,18 @@ |
3 | 3 | #include <linux/pci-aspm.h> |
4 | 4 | #include "pci.h" |
5 | 5 | |
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 | + | |
6 | 18 | static void pci_stop_dev(struct pci_dev *dev) |
7 | 19 | { |
8 | 20 | pci_pme_active(dev, false); |
... | ... | @@ -25,6 +37,11 @@ |
25 | 37 | |
26 | 38 | device_del(&dev->dev); |
27 | 39 | |
40 | + down_write(&pci_bus_sem); | |
41 | + list_del(&dev->bus_list); | |
42 | + up_write(&pci_bus_sem); | |
43 | + | |
44 | + pci_free_resources(dev); | |
28 | 45 | put_device(&dev->dev); |
29 | 46 | } |
30 | 47 |