diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-07 09:02:26 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-07 09:02:26 -0800 |
commit | 37969581301e50872a1ae84dc73962b5f7ee6b76 (patch) | |
tree | 35bbd6a07f903f248f4bd209b8d194a922415fe0 /arch/powerpc/platforms/pseries/xics.c | |
parent | 80ff8a805113850a3ffafcc8e6eaa1fdd51b02f3 (diff) | |
parent | 24f1a849614ba1805e26a05da7cc8c6bd67490ea (diff) | |
download | op-kernel-dev-37969581301e50872a1ae84dc73962b5f7ee6b76.zip op-kernel-dev-37969581301e50872a1ae84dc73962b5f7ee6b76.tar.gz |
Merge branch 'for-2.6.25' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'for-2.6.25' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (69 commits)
[POWERPC] Add SPE registers to core dumps
[POWERPC] Use regset code for compat PTRACE_*REGS* calls
[POWERPC] Use generic compat_sys_ptrace
[POWERPC] Use generic compat_ptrace_request
[POWERPC] Use generic ptrace peekdata/pokedata
[POWERPC] Use regset code for PTRACE_*REGS* requests
[POWERPC] Switch to generic compat_binfmt_elf code
[POWERPC] Switch to using user_regset-based core dumps
[POWERPC] Add user_regset compat support
[POWERPC] Add user_regset_view definitions
[POWERPC] Use user_regset accessors for GPRs
[POWERPC] ptrace accessors for special regs MSR and TRAP
[POWERPC] Use user_regset accessors for SPE regs
[POWERPC] Use user_regset accessors for altivec regs
[POWERPC] Use user_regset accessors for FP regs
[POWERPC] mpc52xx: fix compile error introduce when rebasing patch
[POWERPC] 4xx: PCIe indirect DCR spinlock fix.
[POWERPC] Add missing native dcr dcr_ind_lock spinlock
[POWERPC] 4xx: Fix offset value on Warp board
[POWERPC] 4xx: Add 440EPx Sequoia ehci dts entry
...
Diffstat (limited to 'arch/powerpc/platforms/pseries/xics.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/xics.c | 118 |
1 files changed, 56 insertions, 62 deletions
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 8f8dd9c..ca52b58 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -160,6 +160,46 @@ static inline void lpar_qirr_info(int n_cpu , u8 value) /* High level handlers and init code */ +static void xics_update_irq_servers(void) +{ + int i, j; + struct device_node *np; + u32 ilen; + const u32 *ireg, *isize; + u32 hcpuid; + + /* Find the server numbers for the boot cpu. */ + np = of_get_cpu_node(boot_cpuid, NULL); + BUG_ON(!np); + + ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); + if (!ireg) { + of_node_put(np); + return; + } + + i = ilen / sizeof(int); + hcpuid = get_hard_smp_processor_id(boot_cpuid); + + /* Global interrupt distribution server is specified in the last + * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last + * entry fom this property for current boot cpu id and use it as + * default distribution server + */ + for (j = 0; j < i; j += 2) { + if (ireg[j] == hcpuid) { + default_server = hcpuid; + default_distrib_server = ireg[j+1]; + + isize = of_get_property(np, + "ibm,interrupt-server#-size", NULL); + if (isize) + interrupt_server_size = *isize; + } + } + + of_node_put(np); +} #ifdef CONFIG_SMP static int get_irq_server(unsigned int virq, unsigned int strict_check) @@ -169,6 +209,9 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check) cpumask_t cpumask = irq_desc[virq].affinity; cpumask_t tmp = CPU_MASK_NONE; + if (! cpu_isset(default_server, cpu_online_map)) + xics_update_irq_servers(); + if (!distribute_irqs) return default_server; @@ -658,39 +701,11 @@ static void __init xics_setup_8259_cascade(void) set_irq_chained_handler(cascade, pseries_8259_cascade); } -static struct device_node *cpuid_to_of_node(int cpu) -{ - struct device_node *np; - u32 hcpuid = get_hard_smp_processor_id(cpu); - - for_each_node_by_type(np, "cpu") { - int i, len; - const u32 *intserv; - - intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", - &len); - - if (!intserv) - intserv = of_get_property(np, "reg", &len); - - i = len / sizeof(u32); - - while (i--) - if (intserv[i] == hcpuid) - return np; - } - - return NULL; -} - void __init xics_init_IRQ(void) { - int i, j; struct device_node *np; - u32 ilen, indx = 0; - const u32 *ireg, *isize; + u32 indx = 0; int found = 0; - u32 hcpuid; ppc64_boot_msg(0x20, "XICS Init"); @@ -709,34 +724,7 @@ void __init xics_init_IRQ(void) return; xics_init_host(); - - /* Find the server numbers for the boot cpu. */ - np = cpuid_to_of_node(boot_cpuid); - BUG_ON(!np); - ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); - if (!ireg) - goto skip_gserver_check; - i = ilen / sizeof(int); - hcpuid = get_hard_smp_processor_id(boot_cpuid); - - /* Global interrupt distribution server is specified in the last - * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last - * entry fom this property for current boot cpu id and use it as - * default distribution server - */ - for (j = 0; j < i; j += 2) { - if (ireg[j] == hcpuid) { - default_server = hcpuid; - default_distrib_server = ireg[j+1]; - - isize = of_get_property(np, - "ibm,interrupt-server#-size", NULL); - if (isize) - interrupt_server_size = *isize; - } - } -skip_gserver_check: - of_node_put(np); + xics_update_irq_servers(); if (firmware_has_feature(FW_FEATURE_LPAR)) ppc_md.get_irq = xics_get_irq_lpar; @@ -775,11 +763,9 @@ void xics_request_IPIs(void) } #endif /* CONFIG_SMP */ -void xics_teardown_cpu(int secondary) +void xics_teardown_cpu() { int cpu = smp_processor_id(); - unsigned int ipi; - struct irq_desc *desc; xics_set_cpu_priority(0); @@ -790,9 +776,17 @@ void xics_teardown_cpu(int secondary) lpar_qirr_info(cpu, 0xff); else direct_qirr_info(cpu, 0xff); +} + +void xics_kexec_teardown_cpu(int secondary) +{ + unsigned int ipi; + struct irq_desc *desc; + + xics_teardown_cpu(); /* - * we need to EOI the IPI if we got here from kexec down IPI + * we need to EOI the IPI * * probably need to check all the other interrupts too * should we be flagging idle loop instead? @@ -880,8 +874,8 @@ void xics_migrate_irqs_away(void) virq, cpu); /* Reset affinity to all cpus */ + irq_desc[virq].affinity = CPU_MASK_ALL; desc->chip->set_affinity(virq, CPU_MASK_ALL); - irq_desc[irq].affinity = CPU_MASK_ALL; unlock: spin_unlock_irqrestore(&desc->lock, flags); } |