summary refs log tree commit diff
path: root/drivers/pci
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-12-28 16:54:33 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2008-12-28 16:54:33 -0800
commit3c92ec8ae91ecf59d88c798301833d7cf83f2179 (patch)
tree08a38cd3523c42bd49882f17cd501fd879e7ca1c /drivers/pci
parentc4c9f0183b7c4e97836e8fecbb67898b06c47e78 (diff)
parentca9153a3a2a7556d091dfe080e42b0e67881fff6 (diff)
downloadlinux-3c92ec8ae91ecf59d88c798301833d7cf83f2179.tar.gz
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (144 commits)
  powerpc/44x: Support 16K/64K base page sizes on 44x
  powerpc: Force memory size to be a multiple of PAGE_SIZE
  powerpc/32: Wire up the trampoline code for kdump
  powerpc/32: Add the ability for a classic ppc kernel to be loaded at 32M
  powerpc/32: Allow __ioremap on RAM addresses for kdump kernel
  powerpc/32: Setup OF properties for kdump
  powerpc/32/kdump: Implement crash_setup_regs() using ppc_save_regs()
  powerpc: Prepare xmon_save_regs for use with kdump
  powerpc: Remove default kexec/crash_kernel ops assignments
  powerpc: Make default kexec/crash_kernel ops implicit
  powerpc: Setup OF properties for ppc32 kexec
  powerpc/pseries: Fix cpu hotplug
  powerpc: Fix KVM build on ppc440
  powerpc/cell: add QPACE as a separate Cell platform
  powerpc/cell: fix build breakage with CONFIG_SPUFS disabled
  powerpc/mpc5200: fix error paths in PSC UART probe function
  powerpc/mpc5200: add rts/cts handling in PSC UART driver
  powerpc/mpc5200: Make PSC UART driver update serial errors counters
  powerpc/mpc5200: Remove obsolete code from mpc5200 MDIO driver
  powerpc/mpc5200: Add MDMA/UDMA support to MPC5200 ATA driver
  ...

Fix trivial conflict in drivers/char/Makefile as per Paul's directions
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c69
1 files changed, 30 insertions, 39 deletions
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 9c2a22fed18b..4e3e0382c16e 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -14,6 +14,9 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  */
+
+#undef DEBUG
+
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/string.h>
@@ -151,20 +154,20 @@ static void dlpar_pci_add_bus(struct device_node *dn)
 		return;
 	}
 
+	/* Scan below the new bridge */
 	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 	    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
 		of_scan_pci_bridge(dn, dev);
 
-	pcibios_fixup_new_pci_devices(dev->subordinate);
-
-	/* Claim new bus resources */
-	pcibios_claim_one_bus(dev->bus);
-
 	/* Map IO space for child bus, which may or may not succeed */
 	pcibios_map_io_space(dev->subordinate);
 
-	/* Add new devices to global lists.  Register in proc, sysfs. */
-	pci_bus_add_devices(phb->bus);
+	/* Finish adding it : resource allocation, adding devices, etc...
+	 * Note that we need to perform the finish pass on the -parent-
+	 * bus of the EADS bridge so the bridge device itself gets
+	 * properly added
+	 */
+	pcibios_finish_adding_to_bus(phb->bus);
 }
 
 static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
@@ -203,27 +206,6 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
 	return 0;
 }
 
-static int dlpar_remove_root_bus(struct pci_controller *phb)
-{
-	struct pci_bus *phb_bus;
-	int rc;
-
-	phb_bus = phb->bus;
-	if (!(list_empty(&phb_bus->children) &&
-	      list_empty(&phb_bus->devices))) {
-		return -EBUSY;
-	}
-
-	rc = pcibios_remove_root_bus(phb);
-	if (rc)
-		return -EIO;
-
-	device_unregister(phb_bus->bridge);
-	pci_remove_bus(phb_bus);
-
-	return 0;
-}
-
 static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
 {
 	struct slot *slot;
@@ -235,18 +217,15 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
 
 	/* If pci slot is hotplugable, use hotplug to remove it */
 	slot = find_php_slot(dn);
-	if (slot) {
-		if (rpaphp_deregister_slot(slot)) {
-			printk(KERN_ERR
-				"%s: unable to remove hotplug slot %s\n",
-				__func__, drc_name);
-			return -EIO;
-		}
+	if (slot && rpaphp_deregister_slot(slot)) {
+		printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
+		       __func__, drc_name);
+		return -EIO;
 	}
 
 	pdn = dn->data;
 	BUG_ON(!pdn || !pdn->phb);
-	rc = dlpar_remove_root_bus(pdn->phb);
+	rc = remove_phb_dynamic(pdn->phb);
 	if (rc < 0)
 		return rc;
 
@@ -378,26 +357,38 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
 	if (!bus)
 		return -EINVAL;
 
-	/* If pci slot is hotplugable, use hotplug to remove it */
+	pr_debug("PCI: Removing PCI slot below EADS bridge %s\n",
+		 bus->self ? pci_name(bus->self) : "<!PHB!>");
+
 	slot = find_php_slot(dn);
 	if (slot) {
+		pr_debug("PCI: Removing hotplug slot for %04x:%02x...\n",
+			 pci_domain_nr(bus), bus->number);
+
 		if (rpaphp_deregister_slot(slot)) {
 			printk(KERN_ERR
 				"%s: unable to remove hotplug slot %s\n",
 				__func__, drc_name);
 			return -EIO;
 		}
-	} else
-		pcibios_remove_pci_devices(bus);
+	}
+
+	/* Remove all devices below slot */
+	pcibios_remove_pci_devices(bus);
 
+	/* Unmap PCI IO space */
 	if (pcibios_unmap_io_space(bus)) {
 		printk(KERN_ERR "%s: failed to unmap bus range\n",
 			__func__);
 		return -ERANGE;
 	}
 
+	/* Remove the EADS bridge device itself */
 	BUG_ON(!bus->self);
+	pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self));
+	eeh_remove_bus_device(bus->self);
 	pci_remove_bus_device(bus->self);
+
 	return 0;
 }