aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/remove.c
diff options
context:
space:
mode:
authorZhang Yanmin <yanmin.zhang@intel.com>2006-06-02 00:35:43 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-06-21 15:00:01 -0400
commitd71374dafbba7ec3f67371d3b7e9f6310a588808 (patch)
tree116dcd65fde3701d10fea954cdbd5bb063182b2c /drivers/pci/remove.c
parent733a7fe12248072e1bca729c88a26298666f1956 (diff)
[PATCH] PCI: fix race with pci_walk_bus and pci_destroy_dev
pci_walk_bus has a race with pci_destroy_dev. When cb is called in pci_walk_bus, pci_destroy_dev might unlink the dev pointed by next. Later on in the next loop, pointer next becomes NULL and cause kernel panic. Below patch against 2.6.17-rc4 fixes it by changing pci_bus_lock (spin_lock) to pci_bus_sem (rw_semaphore). Signed-off-by: Zhang Yanmin <yanmin.zhang@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/remove.c')
-rw-r--r--drivers/pci/remove.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 1a6bf9de166f..99ffbd478b29 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -22,18 +22,18 @@ static void pci_destroy_dev(struct pci_dev *dev)
22 pci_proc_detach_device(dev); 22 pci_proc_detach_device(dev);
23 pci_remove_sysfs_dev_files(dev); 23 pci_remove_sysfs_dev_files(dev);
24 device_unregister(&dev->dev); 24 device_unregister(&dev->dev);
25 spin_lock(&pci_bus_lock); 25 down_write(&pci_bus_sem);
26 list_del(&dev->global_list); 26 list_del(&dev->global_list);
27 dev->global_list.next = dev->global_list.prev = NULL; 27 dev->global_list.next = dev->global_list.prev = NULL;
28 spin_unlock(&pci_bus_lock); 28 up_write(&pci_bus_sem);
29 } 29 }
30 30
31 /* Remove the device from the device lists, and prevent any further 31 /* Remove the device from the device lists, and prevent any further
32 * list accesses from this device */ 32 * list accesses from this device */
33 spin_lock(&pci_bus_lock); 33 down_write(&pci_bus_sem);
34 list_del(&dev->bus_list); 34 list_del(&dev->bus_list);
35 dev->bus_list.next = dev->bus_list.prev = NULL; 35 dev->bus_list.next = dev->bus_list.prev = NULL;
36 spin_unlock(&pci_bus_lock); 36 up_write(&pci_bus_sem);
37 37
38 pci_free_resources(dev); 38 pci_free_resources(dev);
39 pci_dev_put(dev); 39 pci_dev_put(dev);
@@ -62,9 +62,9 @@ void pci_remove_bus(struct pci_bus *pci_bus)
62{ 62{
63 pci_proc_detach_bus(pci_bus); 63 pci_proc_detach_bus(pci_bus);
64 64
65 spin_lock(&pci_bus_lock); 65 down_write(&pci_bus_sem);
66 list_del(&pci_bus->node); 66 list_del(&pci_bus->node);
67 spin_unlock(&pci_bus_lock); 67 up_write(&pci_bus_sem);
68 pci_remove_legacy_files(pci_bus); 68 pci_remove_legacy_files(pci_bus);
69 class_device_remove_file(&pci_bus->class_dev, 69 class_device_remove_file(&pci_bus->class_dev,
70 &class_device_attr_cpuaffinity); 70 &class_device_attr_cpuaffinity);