diff options
Diffstat (limited to 'drivers/pcmcia/cardbus.c')
| -rw-r--r-- | drivers/pcmcia/cardbus.c | 28 |
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(); } |
