diff options
author | John Rose <johnrose@austin.ibm.com> | 2005-11-04 22:38:50 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-11-11 01:09:17 +0100 |
commit | 5fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6 (patch) | |
tree | 156eef01eb5fb8431478f77ed01a2490064668a8 /drivers/pci/hotplug/rpaphp_pci.c | |
parent | [PATCH] PCI: removed unneeded .owner field from struct pci_driver (diff) | |
download | linux-5fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6.tar.xz linux-5fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6.zip |
[PATCH] dlpar regression for ppc64 - probe change
This patch contains the driver bits for enabling DLPAR and PCI Hotplug
for the new OF-based PCI probe. This functionality was regressed when
the new PCI approach was introduced. Please apply if appropriate.
Signed-off-by: John Rose <johnrose@austin.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/hotplug/rpaphp_pci.c')
-rw-r--r-- | drivers/pci/hotplug/rpaphp_pci.c | 76 |
1 files changed, 56 insertions, 20 deletions
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index f7c12d7dfcfc..a7859a84d1ae 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -154,8 +154,7 @@ exit: } /* Must be called before pci_bus_add_devices */ -static void -rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) +void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) { struct pci_dev *dev; @@ -184,6 +183,20 @@ rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) } } +static void rpaphp_eeh_add_bus_device(struct pci_bus *bus) +{ + struct pci_dev *dev; + + list_for_each_entry(dev, &bus->devices, bus_list) { + eeh_add_device_late(dev); + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + struct pci_bus *subbus = dev->subordinate; + if (subbus) + rpaphp_eeh_add_bus_device (subbus); + } + } +} + static int rpaphp_pci_config_bridge(struct pci_dev *dev) { u8 sec_busno; @@ -217,6 +230,13 @@ static int rpaphp_pci_config_bridge(struct pci_dev *dev) return 0; } +void rpaphp_init_new_devs(struct pci_bus *bus) +{ + rpaphp_fixup_new_pci_devices(bus, 0); + rpaphp_eeh_add_bus_device(bus); +} +EXPORT_SYMBOL_GPL(rpaphp_init_new_devs); + /***************************************************************************** rpaphp_pci_config_slot() will configure all devices under the given slot->dn and return the the first pci_dev. @@ -233,36 +253,51 @@ rpaphp_pci_config_slot(struct pci_bus *bus) if (!dn || !dn->child) return NULL; - slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { + of_scan_bus(dn, bus); + if (list_empty(&bus->devices)) { + err("%s: No new device found\n", __FUNCTION__); + return NULL; + } - /* pci_scan_slot should find all children */ - num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); - if (num) { - rpaphp_fixup_new_pci_devices(bus, 1); + rpaphp_init_new_devs(bus); pci_bus_add_devices(bus); - } - if (list_empty(&bus->devices)) { - err("%s: No new device found\n", __FUNCTION__); - return NULL; - } - list_for_each_entry(dev, &bus->devices, bus_list) { - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) - rpaphp_pci_config_bridge(dev); + dev = list_entry(&bus->devices, struct pci_dev, bus_list); + } else { + slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); + + /* pci_scan_slot should find all children */ + num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); + if (num) { + rpaphp_fixup_new_pci_devices(bus, 1); + pci_bus_add_devices(bus); + } + if (list_empty(&bus->devices)) { + err("%s: No new device found\n", __FUNCTION__); + return NULL; + } + list_for_each_entry(dev, &bus->devices, bus_list) { + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) + rpaphp_pci_config_bridge(dev); + + rpaphp_eeh_add_bus_device(bus); + } } return dev; } -static void enable_eeh(struct device_node *dn) +void rpaphp_eeh_init_nodes(struct device_node *dn) { struct device_node *sib; for (sib = dn->child; sib; sib = sib->sibling) - enable_eeh(sib); + rpaphp_eeh_init_nodes(sib); eeh_add_device_early(dn); return; } +EXPORT_SYMBOL_GPL(rpaphp_eeh_init_nodes); static void print_slot_pci_funcs(struct pci_bus *bus) { @@ -289,7 +324,7 @@ int rpaphp_config_pci_adapter(struct pci_bus *bus) if (!dn) goto exit; - enable_eeh(dn); + rpaphp_eeh_init_nodes(dn); dev = rpaphp_pci_config_slot(bus); if (!dev) { err("%s: can't find any devices.\n", __FUNCTION__); @@ -331,6 +366,7 @@ int rpaphp_unconfig_pci_adapter(struct pci_bus *bus) } return 0; } +EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter); static int setup_pci_hotplug_slot_info(struct slot *slot) { @@ -444,8 +480,8 @@ int rpaphp_enable_pci_slot(struct slot *slot) retval = rpaphp_config_pci_adapter(slot->bus); if (!retval) { slot->state = CONFIGURED; - dbg("%s: PCI devices in slot[%s] has been configured\n", - __FUNCTION__, slot->name); + info("%s: devices in slot[%s] configured\n", + __FUNCTION__, slot->name); } else { slot->state = NOT_CONFIGURED; dbg("%s: no pci_dev struct for adapter in slot[%s]\n", |