summaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-01-10 15:25:34 +0100
committerBjorn Helgaas <bhelgaas@google.com>2014-01-14 20:14:25 +0100
commit5ef68e8867ca9d979644d05c6045b2c79d8989de (patch)
tree823c6a0775cf6d761691a3ddd3965b324bd39aa9 /drivers/pcmcia
parentACPI / hotplug / PCI: Use global PCI rescan-remove locking (diff)
downloadlinux-5ef68e8867ca9d979644d05c6045b2c79d8989de.tar.xz
linux-5ef68e8867ca9d979644d05c6045b2c79d8989de.zip
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>
Diffstat (limited to 'drivers/pcmcia')
-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)
struct pci_dev *dev;
unsigned int max, pass;
+ pci_lock_rescan_remove();
+
s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
pci_fixup_cardbus(bus);
@@ -93,6 +95,7 @@ int __ref cb_alloc(struct pcmcia_socket *s)
pci_bus_add_devices(bus);
+ pci_unlock_rescan_remove();
return 0;
}
@@ -115,6 +118,10 @@ void cb_free(struct pcmcia_socket *s)
if (!bus)
return;
+ pci_lock_rescan_remove();
+
list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list)
pci_stop_and_remove_bus_device(dev);
+
+ pci_unlock_rescan_remove();
}