diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-28 16:54:33 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-28 16:54:33 -0800 |
commit | 3c92ec8ae91ecf59d88c798301833d7cf83f2179 (patch) | |
tree | 08a38cd3523c42bd49882f17cd501fd879e7ca1c /drivers/pci | |
parent | c4c9f0183b7c4e97836e8fecbb67898b06c47e78 (diff) | |
parent | ca9153a3a2a7556d091dfe080e42b0e67881fff6 (diff) |
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.c | 69 |
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; } |