diff options
author | Paul Mackerras <paulus@samba.org> | 2005-08-04 15:53:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-08-04 16:00:55 -0400 |
commit | 6d22d85a852b72398a81b8e476977b28b4400f7c (patch) | |
tree | 3824c246813b7c326bceedc0b8c3c8ca49c7fd0b | |
parent | 48f1f5328267f52a34e61b8b0e6fc55a23c1348a (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>
-rw-r--r-- | arch/ppc64/kernel/machine_kexec.c | 6 | ||||
-rw-r--r-- | arch/ppc64/kernel/mpic.c | 4 | ||||
-rw-r--r-- | arch/ppc64/kernel/mpic.h | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/xics.c | 31 | ||||
-rw-r--r-- | include/asm-ppc64/machdep.h | 2 | ||||
-rw-r--r-- | include/asm-ppc64/xics.h | 2 |
6 files changed, 24 insertions, 23 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) | |||
185 | void kexec_smp_down(void *arg) | 185 | void 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 | */ |
800 | void mpic_teardown_this_cpu(void) | 800 | void 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); | |||
256 | extern void mpic_setup_this_cpu(void); | 256 | extern 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 ...) */ |
259 | extern void mpic_teardown_this_cpu(void); | 259 | extern void mpic_teardown_this_cpu(int secondary); |
260 | 260 | ||
261 | /* Request IPIs on primary mpic */ | 261 | /* Request IPIs on primary mpic */ |
262 | extern void mpic_request_ipis(void); | 262 | 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) | |||
647 | } | 647 | } |
648 | } | 648 | } |
649 | 649 | ||
650 | void xics_teardown_cpu(void) | 650 | void 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 |
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 { | |||
84 | 84 | ||
85 | void (*init_IRQ)(void); | 85 | void (*init_IRQ)(void); |
86 | int (*get_irq)(struct pt_regs *); | 86 | int (*get_irq)(struct pt_regs *); |
87 | void (*cpu_irq_down)(void); | 87 | void (*cpu_irq_down)(int secondary); |
88 | 88 | ||
89 | /* PCI stuff */ | 89 | /* PCI stuff */ |
90 | void (*pcibios_fixup)(void); | 90 | 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 @@ | |||
17 | void xics_init_IRQ(void); | 17 | void xics_init_IRQ(void); |
18 | int xics_get_irq(struct pt_regs *); | 18 | int xics_get_irq(struct pt_regs *); |
19 | void xics_setup_cpu(void); | 19 | void xics_setup_cpu(void); |
20 | void xics_teardown_cpu(void); | 20 | void xics_teardown_cpu(int secondary); |
21 | void xics_cause_IPI(int cpu); | 21 | void xics_cause_IPI(int cpu); |
22 | void xics_request_IPIs(void); | 22 | void xics_request_IPIs(void); |
23 | void xics_migrate_irqs_away(void); | 23 | void xics_migrate_irqs_away(void); |