[PATCH] powerpc: properly configure DDR/P5IOC children devs

The dynamic add path for PCI Host Bridges can fail to configure children
adapters under P5IOC controllers.  It fails to properly fixup bus/device
resources, and it fails to properly enable EEH.  Both of these steps
need to occur before any children devices are enabled in
pci_bus_add_devices().

Signed-off-by: John Rose <johnrose@austin.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index c367520..ba92bab7 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -589,7 +589,6 @@
 #endif /* CONFIG_PPC_MULTIPLATFORM */
 	if (mode == PCI_PROBE_NORMAL)
 		hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
-	pci_bus_add_devices(bus);
 }
 
 static int __init pcibios_init(void)
@@ -608,8 +607,10 @@
 	printk("PCI: Probing PCI hardware\n");
 
 	/* Scan all of the recorded PCI controllers.  */
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		scan_phb(hose);
+		pci_bus_add_devices(hose->bus);
+	}
 
 #ifndef CONFIG_PPC_ISERIES
 	if (pci_probe_only)
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 5579f65..7442775 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -280,8 +280,7 @@
 	return 0;
 }
 
-static int __devinit setup_phb(struct device_node *dev,
-			       struct pci_controller *phb)
+int __devinit setup_phb(struct device_node *dev, struct pci_controller *phb)
 {
 	if (is_python(dev))
 		python_countermeasures(dev);
@@ -359,27 +358,6 @@
 	return 0;
 }
 
-struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
-{
-	struct pci_controller *phb;
-	int primary;
-
-	primary = list_empty(&hose_list);
-	phb = pcibios_alloc_controller(dn);
-	if (!phb)
-		return NULL;
-	setup_phb(dn, phb);
-	pci_process_bridge_OF_ranges(phb, dn, primary);
-
-	pci_setup_phb_io_dynamic(phb, primary);
-
-	pci_devs_phb_init_dynamic(phb);
-	scan_phb(phb);
-
-	return phb;
-}
-EXPORT_SYMBOL(init_phb_dynamic);
-
 /* RPA-specific bits for removing PHBs */
 int pcibios_remove_root_bus(struct pci_controller *phb)
 {
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index f3bad90..44abdeb 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -27,6 +27,7 @@
 
 #include <linux/pci.h>
 #include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
 
 static struct pci_bus *
 find_bus_among_children(struct pci_bus *bus,
@@ -179,3 +180,30 @@
 	}
 }
 EXPORT_SYMBOL_GPL(pcibios_add_pci_devices);
+
+struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
+{
+	struct pci_controller *phb;
+	int primary;
+
+	primary = list_empty(&hose_list);
+	phb = pcibios_alloc_controller(dn);
+	if (!phb)
+		return NULL;
+	setup_phb(dn, phb);
+	pci_process_bridge_OF_ranges(phb, dn, 0);
+
+	pci_setup_phb_io_dynamic(phb, primary);
+
+	pci_devs_phb_init_dynamic(phb);
+
+	if (dn->child)
+		eeh_add_device_tree_early(dn);
+
+	scan_phb(phb);
+	pcibios_fixup_new_pci_devices(phb->bus, 0);
+	pci_bus_add_devices(phb->bus);
+
+	return phb;
+}
+EXPORT_SYMBOL_GPL(init_phb_dynamic);
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h
index f80482c..cf79bc7 100644
--- a/include/asm-powerpc/ppc-pci.h
+++ b/include/asm-powerpc/ppc-pci.h
@@ -38,6 +38,7 @@
 
 void pci_devs_phb_init(void);
 void pci_devs_phb_init_dynamic(struct pci_controller *phb);
+int setup_phb(struct device_node *dev, struct pci_controller *phb);
 void __devinit scan_phb(struct pci_controller *hose);
 
 /* From rtas_pci.h */