aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-08-04 15:53:37 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-08-04 16:00:55 -0400
commit6d22d85a852b72398a81b8e476977b28b4400f7c (patch)
tree3824c246813b7c326bceedc0b8c3c8ca49c7fd0b /arch
parent48f1f5328267f52a34e61b8b0e6fc55a23c1348a (diff)
[PATCH] ppc64: fix for kexec boot issue
The kexec boot is not successful on some power machines since all CPUs are getting removed from global interrupt queue (GIQ) before kexec boot. Some systems always expect at least one CPU in GIQ. Hence, this patch will make sure that only secondary CPUs are removed from GIQ. Signed-off-by: Haren Myneni <hbabu@us.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/ppc64/kernel/machine_kexec.c6
-rw-r--r--arch/ppc64/kernel/mpic.c4
-rw-r--r--arch/ppc64/kernel/mpic.h2
-rw-r--r--arch/ppc64/kernel/xics.c31
4 files changed, 22 insertions, 21 deletions
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)
185void kexec_smp_down(void *arg) 185void kexec_smp_down(void *arg)
186{ 186{
187 if (ppc_md.cpu_irq_down) 187 if (ppc_md.cpu_irq_down)
188 ppc_md.cpu_irq_down(); 188 ppc_md.cpu_irq_down(1);
189 189
190 local_irq_disable(); 190 local_irq_disable();
191 kexec_smp_wait(); 191 kexec_smp_wait();
@@ -232,7 +232,7 @@ static void kexec_prepare_cpus(void)
232 232
233 /* after we tell the others to go down */ 233 /* after we tell the others to go down */
234 if (ppc_md.cpu_irq_down) 234 if (ppc_md.cpu_irq_down)
235 ppc_md.cpu_irq_down(); 235 ppc_md.cpu_irq_down(0);
236 236
237 put_cpu(); 237 put_cpu();
238 238
@@ -255,7 +255,7 @@ static void kexec_prepare_cpus(void)
255 */ 255 */
256 smp_release_cpus(); 256 smp_release_cpus();
257 if (ppc_md.cpu_irq_down) 257 if (ppc_md.cpu_irq_down)
258 ppc_md.cpu_irq_down(); 258 ppc_md.cpu_irq_down(0);
259 local_irq_disable(); 259 local_irq_disable();
260} 260}
261 261
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)
794 794
795/* 795/*
796 * XXX: someone who knows mpic should check this. 796 * XXX: someone who knows mpic should check this.
797 * do we need to eoi the ipi here (see xics comments)? 797 * do we need to eoi the ipi including for kexec cpu here (see xics comments)?
798 * or can we reset the mpic in the new kernel? 798 * or can we reset the mpic in the new kernel?
799 */ 799 */
800void mpic_teardown_this_cpu(void) 800void mpic_teardown_this_cpu(int secondary)
801{ 801{
802 struct mpic *mpic = mpic_primary; 802 struct mpic *mpic = mpic_primary;
803 unsigned long flags; 803 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);
256extern void mpic_setup_this_cpu(void); 256extern void mpic_setup_this_cpu(void);
257 257
258/* Clean up for kexec (or cpu offline or ...) */ 258/* Clean up for kexec (or cpu offline or ...) */
259extern void mpic_teardown_this_cpu(void); 259extern void mpic_teardown_this_cpu(int secondary);
260 260
261/* Request IPIs on primary mpic */ 261/* Request IPIs on primary mpic */
262extern void mpic_request_ipis(void); 262extern 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)
647 } 647 }
648} 648}
649 649
650void xics_teardown_cpu(void) 650void xics_teardown_cpu(int secondary)
651{ 651{
652 int cpu = smp_processor_id(); 652 int cpu = smp_processor_id();
653 int status;
654 653
655 ops->cppr_info(cpu, 0x00); 654 ops->cppr_info(cpu, 0x00);
656 iosync(); 655 iosync();
657 656
658 /* 657 /*
659 * we need to EOI the IPI if we got here from kexec down IPI 658 * Some machines need to have at least one cpu in the GIQ,
660 * 659 * so leave the master cpu in the group.
661 * xics doesn't care if we duplicate an EOI as long as we
662 * don't EOI and raise priority.
663 *
664 * probably need to check all the other interrupts too
665 * should we be flagging idle loop instead?
666 * or creating some task to be scheduled?
667 */ 660 */
668 ops->xirr_info_set(cpu, XICS_IPI); 661 if (secondary) {
669 662 /*
670 status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, 663 * we need to EOI the IPI if we got here from kexec down IPI
671 (1UL << interrupt_server_size) - 1 - default_distrib_server, 0); 664 *
672 WARN_ON(status != 0); 665 * probably need to check all the other interrupts too
666 * should we be flagging idle loop instead?
667 * or creating some task to be scheduled?
668 */
669 ops->xirr_info_set(cpu, XICS_IPI);
670 rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
671 (1UL << interrupt_server_size) - 1 -
672 default_distrib_server, 0);
673 }
673} 674}
674 675
675#ifdef CONFIG_HOTPLUG_CPU 676#ifdef CONFIG_HOTPLUG_CPU