Commit 18126f35 authored by Linas Vepstas's avatar Linas Vepstas Committed by Paul Mackerras

[PATCH] ppc64: bugfix: crash on PCI hotplug

09-hotplug-bugfix.patch

In the current 2.6.14-rc2-git6 kernel, performing a Dynamic LPAR Add
of a hotplug slot will crash the system, with the following (abbreviated)
stack trace:

cpu 0x3: Vector: 700 (Program Check) at [c000000053dff7f0]
    pc: c0000000004f5974: .__alloc_bootmem+0x0/0xb0
    lr: c0000000000258a0: .update_dn_pci_info+0x108/0x118
        c0000000000257c8 .update_dn_pci_info+0x30/0x118 (unreliable)
        c0000000000258fc .pci_dn_reconfig_notifier+0x4c/0x64
        c000000000060754 .notifier_call_chain+0x68/0x9c

The root cause was that __init __alloc_bootmem() was called long after
boot had finished, resulting in a crash because this routine is undefined
after boot time.  The patch below fixes this crash, and adds some docs to
clarify the code.
Signed-off-by: default avatarLinas Vepstas <linas@austin.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 5c1344e9
...@@ -43,7 +43,7 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data) ...@@ -43,7 +43,7 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
u32 *regs; u32 *regs;
struct pci_dn *pdn; struct pci_dn *pdn;
if (phb->is_dynamic) if (mem_init_done)
pdn = kmalloc(sizeof(*pdn), GFP_KERNEL); pdn = kmalloc(sizeof(*pdn), GFP_KERNEL);
else else
pdn = alloc_bootmem(sizeof(*pdn)); pdn = alloc_bootmem(sizeof(*pdn));
...@@ -120,6 +120,14 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, ...@@ -120,6 +120,14 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
return NULL; return NULL;
} }
/**
* pci_devs_phb_init_dynamic - setup pci devices under this PHB
* phb: pci-to-host bridge (top-level bridge connecting to cpu)
*
* This routine is called both during boot, (before the memory
* subsystem is set up, before kmalloc is valid) and during the
* dynamic lpar operation of adding a PHB to a running system.
*/
void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb) void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
{ {
struct device_node * dn = (struct device_node *) phb->arch_data; struct device_node * dn = (struct device_node *) phb->arch_data;
...@@ -201,9 +209,14 @@ static struct notifier_block pci_dn_reconfig_nb = { ...@@ -201,9 +209,14 @@ static struct notifier_block pci_dn_reconfig_nb = {
.notifier_call = pci_dn_reconfig_notifier, .notifier_call = pci_dn_reconfig_notifier,
}; };
/* /**
* Actually initialize the phbs. * pci_devs_phb_init - Initialize phbs and pci devs under them.
* The buswalk on this phb has not happened yet. *
* This routine walks over all phb's (pci-host bridges) on the
* system, and sets up assorted pci-related structures
* (including pci info in the device node structs) for each
* pci device found underneath. This routine runs once,
* early in the boot sequence.
*/ */
void __init pci_devs_phb_init(void) void __init pci_devs_phb_init(void)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment