aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-02-01 09:38:29 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-02-01 13:24:31 -0500
commit04480094de7242d08bb62088e713fd7fe00443b4 (patch)
treea8a9806a3f55f5343b6375743c8e107e800c6df6 /drivers
parent8a1f006ad302ea178aefb1f8c67e679c696289e9 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/probe.c21
-rw-r--r--drivers/pci/remove.c17
2 files changed, 19 insertions, 19 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 04796c056d12..6e34498ec9f0 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1208,18 +1208,6 @@ static void pci_release_capabilities(struct pci_dev *dev)
1208 pci_free_cap_save_buffers(dev); 1208 pci_free_cap_save_buffers(dev);
1209} 1209}
1210 1210
1211static 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 * pci_release_dev - free a pci device structure when all users of it are finished. 1212 * pci_release_dev - free a pci device structure when all users of it are finished.
1225 * @dev: device that's been disconnected 1213 * @dev: device that's been disconnected
@@ -1229,14 +1217,9 @@ static void pci_free_resources(struct pci_dev *dev)
1229 */ 1217 */
1230static void pci_release_dev(struct device *dev) 1218static 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
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 1221
1222 pci_dev = to_pci_dev(dev);
1240 pci_release_capabilities(pci_dev); 1223 pci_release_capabilities(pci_dev);
1241 pci_release_of_node(pci_dev); 1224 pci_release_of_node(pci_dev);
1242 pcibios_release_device(pci_dev); 1225 pcibios_release_device(pci_dev);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 4ff36bfa785e..8bd76c9ba21c 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -3,6 +3,18 @@
3#include <linux/pci-aspm.h> 3#include <linux/pci-aspm.h>
4#include "pci.h" 4#include "pci.h"
5 5
6static 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
6static void pci_stop_dev(struct pci_dev *dev) 18static void pci_stop_dev(struct pci_dev *dev)
7{ 19{
8 pci_pme_active(dev, false); 20 pci_pme_active(dev, false);
@@ -25,6 +37,11 @@ static void pci_destroy_dev(struct pci_dev *dev)
25 37
26 device_del(&dev->dev); 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 put_device(&dev->dev); 45 put_device(&dev->dev);
29} 46}
30 47