diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/ppc64/kernel/machine_kexec.c index 5c40bb6788df..4775f12a013c 100644 --- a/arch/ppc64/kernel/machine_kexec.c +++ b/arch/ppc64/kernel/machine_kexec.c @@ -185,7 +185,7 @@ void kexec_copy_flush(struct kimage *image) void kexec_smp_down(void *arg) { if (ppc_md.cpu_irq_down) - ppc_md.cpu_irq_down(); + ppc_md.cpu_irq_down(1); local_irq_disable(); kexec_smp_wait(); @@ -232,7 +232,7 @@ static void kexec_prepare_cpus(void) /* after we tell the others to go down */ if (ppc_md.cpu_irq_down) - ppc_md.cpu_irq_down(); + ppc_md.cpu_irq_down(0); put_cpu(); @@ -255,7 +255,7 @@ static void kexec_prepare_cpus(void) */ smp_release_cpus(); if (ppc_md.cpu_irq_down) - ppc_md.cpu_irq_down(); + ppc_md.cpu_irq_down(0); local_irq_disable(); } diff --git a/arch/ppc64/kernel/mpic.c b/arch/ppc64/kernel/mpic.c index e8fbab1df37f..cc262a05ddb4 100644 --- a/arch/ppc64/kernel/mpic.c +++ b/arch/ppc64/kernel/mpic.c @@ -794,10 +794,10 @@ void mpic_setup_this_cpu(void) /* * XXX: someone who knows mpic should check this. - * do we need to eoi the ipi here (see xics comments)? + * do we need to eoi the ipi including for kexec cpu here (see xics comments)? * or can we reset the mpic in the new kernel? */ -void mpic_teardown_this_cpu(void) +void mpic_teardown_this_cpu(int secondary) { struct mpic *mpic = mpic_primary; unsigned long flags; diff --git a/arch/ppc64/kernel/mpic.h b/arch/ppc64/kernel/mpic.h index 99fbbc9a084c..ca78a7f10528 100644 --- a/arch/ppc64/kernel/mpic.h +++ b/arch/ppc64/kernel/mpic.h @@ -256,7 +256,7 @@ extern unsigned int mpic_irq_get_priority(unsigned int irq); extern void mpic_setup_this_cpu(void); /* Clean up for kexec (or cpu offline or ...) */ -extern void mpic_teardown_this_cpu(void); +extern void mpic_teardown_this_cpu(int secondary); /* Request IPIs on primary mpic */ extern void mpic_request_ipis(void); diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c index 677c4450984a..d9dc6f28d050 100644 --- a/arch/ppc64/kernel/xics.c +++ b/arch/ppc64/kernel/xics.c @@ -647,29 +647,30 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) } } -void xics_teardown_cpu(void) +void xics_teardown_cpu(int secondary) { int cpu = smp_processor_id(); - int status; ops->cppr_info(cpu, 0x00); iosync(); /* - * we need to EOI the IPI if we got here from kexec down IPI - * - * xics doesn't care if we duplicate an EOI as long as we - * don't EOI and raise priority. - * - * probably need to check all the other interrupts too - * should we be flagging idle loop instead? - * or creating some task to be scheduled? + * Some machines need to have at least one cpu in the GIQ, + * so leave the master cpu in the group. */ - ops->xirr_info_set(cpu, XICS_IPI); - - status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, - (1UL << interrupt_server_size) - 1 - default_distrib_server, 0); - WARN_ON(status != 0); + if (secondary) { + /* + * we need to EOI the IPI if we got here from kexec down IPI + * + * probably need to check all the other interrupts too + * should we be flagging idle loop instead? + * or creating some task to be scheduled? + */ + ops->xirr_info_set(cpu, XICS_IPI); + rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, + (1UL << interrupt_server_size) - 1 - + default_distrib_server, 0); + } } #ifdef CONFIG_HOTPLUG_CPU diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h index f0c1d2d92672..f0ef06375947 100644 --- a/include/asm-ppc64/machdep.h +++ b/include/asm-ppc64/machdep.h @@ -84,7 +84,7 @@ struct machdep_calls { void (*init_IRQ)(void); int (*get_irq)(struct pt_regs *); - void (*cpu_irq_down)(void); + void (*cpu_irq_down)(int secondary); /* PCI stuff */ void (*pcibios_fixup)(void); diff --git a/include/asm-ppc64/xics.h b/include/asm-ppc64/xics.h index 0c45e14e26ca..1092af55d707 100644 --- a/include/asm-ppc64/xics.h +++ b/include/asm-ppc64/xics.h @@ -17,7 +17,7 @@ void xics_init_IRQ(void); int xics_get_irq(struct pt_regs *); void xics_setup_cpu(void); -void xics_teardown_cpu(void); +void xics_teardown_cpu(int secondary); void xics_cause_IPI(int cpu); void xics_request_IPIs(void); void xics_migrate_irqs_away(void);