aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-01-10 09:25:34 -0500
committerBjorn Helgaas <bhelgaas@google.com>2014-01-14 14:14:25 -0500
commit5ef68e8867ca9d979644d05c6045b2c79d8989de (patch)
tree823c6a0775cf6d761691a3ddd3965b324bd39aa9
parent9217a984671e8a7e38f1822eba754898066e2ae1 (diff)
pcmcia: Use global PCI rescan-remove locking
Multiple race conditions are possible between the cardbus PCI device addition and removal and the generic PCI bus rescan and device removal that can be triggered via sysfs. To avoid those race conditions make the cardbus code use global PCI rescan-remove locking. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--drivers/pcmcia/cardbus.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index b2a98cdbd0d2..8bde61952d20 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -70,6 +70,8 @@ int __ref cb_alloc(struct pcmcia_socket *s)
70 struct pci_dev *dev; 70 struct pci_dev *dev;
71 unsigned int max, pass; 71 unsigned int max, pass;
72 72
73 pci_lock_rescan_remove();
74
73 s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); 75 s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
74 pci_fixup_cardbus(bus); 76 pci_fixup_cardbus(bus);
75 77
@@ -93,6 +95,7 @@ int __ref cb_alloc(struct pcmcia_socket *s)
93 95
94 pci_bus_add_devices(bus); 96 pci_bus_add_devices(bus);
95 97
98 pci_unlock_rescan_remove();
96 return 0; 99 return 0;
97} 100}
98 101
@@ -115,6 +118,10 @@ void cb_free(struct pcmcia_socket *s)
115 if (!bus) 118 if (!bus)
116 return; 119 return;
117 120
121 pci_lock_rescan_remove();
122
118 list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) 123 list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list)
119 pci_stop_and_remove_bus_device(dev); 124 pci_stop_and_remove_bus_device(dev);
125
126 pci_unlock_rescan_remove();
120} 127}