aboutsummaryrefslogtreecommitdiff
path: root/drivers/pcmcia/cardbus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia/cardbus.c')
-rw-r--r--drivers/pcmcia/cardbus.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index 9a58862f140..4fe4cc4ae19 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -70,14 +70,15 @@ 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);
- max = bus->secondary;
+ max = bus->busn_res.start;
for (pass = 0; pass < 2; pass++)
list_for_each_entry(dev, &bus->devices, bus_list)
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ if (pci_is_bridge(dev))
max = pci_scan_bridge(bus, dev, max, pass);
/*
@@ -91,9 +92,9 @@ int __ref cb_alloc(struct pcmcia_socket *s)
if (s->tune_bridge)
s->tune_bridge(s, bus);
- pci_enable_bridges(bus);
pci_bus_add_devices(bus);
+ pci_unlock_rescan_remove();
return 0;
}
@@ -105,8 +106,21 @@ int __ref cb_alloc(struct pcmcia_socket *s)
*/
void cb_free(struct pcmcia_socket *s)
{
- struct pci_dev *bridge = s->cb_dev;
+ struct pci_dev *bridge, *dev, *tmp;
+ struct pci_bus *bus;
+
+ bridge = s->cb_dev;
+ if (!bridge)
+ return;
+
+ bus = bridge->subordinate;
+ 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);
- if (bridge)
- pci_remove_behind_bridge(bridge);
+ pci_unlock_rescan_remove();
}