aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/crash.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/crash.c')
-rw-r--r--arch/powerpc/kernel/crash.c44
1 files changed, 41 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 6f4613dd05e..417f7b05a9c 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -24,7 +24,7 @@
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/irq.h> 25#include <linux/irq.h>
26#include <linux/types.h> 26#include <linux/types.h>
27#include <linux/lmb.h> 27#include <linux/memblock.h>
28 28
29#include <asm/processor.h> 29#include <asm/processor.h>
30#include <asm/machdep.h> 30#include <asm/machdep.h>
@@ -162,6 +162,34 @@ static void crash_kexec_prepare_cpus(int cpu)
162 /* Leave the IPI callback set */ 162 /* Leave the IPI callback set */
163} 163}
164 164
165/* wait for all the CPUs to hit real mode but timeout if they don't come in */
166#ifdef CONFIG_PPC_STD_MMU_64
167static void crash_kexec_wait_realmode(int cpu)
168{
169 unsigned int msecs;
170 int i;
171
172 msecs = 10000;
173 for (i=0; i < NR_CPUS && msecs > 0; i++) {
174 if (i == cpu)
175 continue;
176
177 while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) {
178 barrier();
179 if (!cpu_possible(i)) {
180 break;
181 }
182 if (!cpu_online(i)) {
183 break;
184 }
185 msecs--;
186 mdelay(1);
187 }
188 }
189 mb();
190}
191#endif
192
165/* 193/*
166 * This function will be called by secondary cpus or by kexec cpu 194 * This function will be called by secondary cpus or by kexec cpu
167 * if soft-reset is activated to stop some CPUs. 195 * if soft-reset is activated to stop some CPUs.
@@ -347,10 +375,12 @@ int crash_shutdown_unregister(crash_shutdown_t handler)
347EXPORT_SYMBOL(crash_shutdown_unregister); 375EXPORT_SYMBOL(crash_shutdown_unregister);
348 376
349static unsigned long crash_shutdown_buf[JMP_BUF_LEN]; 377static unsigned long crash_shutdown_buf[JMP_BUF_LEN];
378static int crash_shutdown_cpu = -1;
350 379
351static int handle_fault(struct pt_regs *regs) 380static int handle_fault(struct pt_regs *regs)
352{ 381{
353 longjmp(crash_shutdown_buf, 1); 382 if (crash_shutdown_cpu == smp_processor_id())
383 longjmp(crash_shutdown_buf, 1);
354 return 0; 384 return 0;
355} 385}
356 386
@@ -375,11 +405,14 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
375 for_each_irq(i) { 405 for_each_irq(i) {
376 struct irq_desc *desc = irq_to_desc(i); 406 struct irq_desc *desc = irq_to_desc(i);
377 407
408 if (!desc || !desc->chip || !desc->chip->eoi)
409 continue;
410
378 if (desc->status & IRQ_INPROGRESS) 411 if (desc->status & IRQ_INPROGRESS)
379 desc->chip->eoi(i); 412 desc->chip->eoi(i);
380 413
381 if (!(desc->status & IRQ_DISABLED)) 414 if (!(desc->status & IRQ_DISABLED))
382 desc->chip->disable(i); 415 desc->chip->shutdown(i);
383 } 416 }
384 417
385 /* 418 /*
@@ -388,6 +421,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
388 */ 421 */
389 old_handler = __debugger_fault_handler; 422 old_handler = __debugger_fault_handler;
390 __debugger_fault_handler = handle_fault; 423 __debugger_fault_handler = handle_fault;
424 crash_shutdown_cpu = smp_processor_id();
391 for (i = 0; crash_shutdown_handles[i]; i++) { 425 for (i = 0; crash_shutdown_handles[i]; i++) {
392 if (setjmp(crash_shutdown_buf) == 0) { 426 if (setjmp(crash_shutdown_buf) == 0) {
393 /* 427 /*
@@ -401,6 +435,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
401 asm volatile("sync; isync"); 435 asm volatile("sync; isync");
402 } 436 }
403 } 437 }
438 crash_shutdown_cpu = -1;
404 __debugger_fault_handler = old_handler; 439 __debugger_fault_handler = old_handler;
405 440
406 /* 441 /*
@@ -412,6 +447,9 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
412 crash_kexec_prepare_cpus(crashing_cpu); 447 crash_kexec_prepare_cpus(crashing_cpu);
413 cpu_set(crashing_cpu, cpus_in_crash); 448 cpu_set(crashing_cpu, cpus_in_crash);
414 crash_kexec_stop_spus(); 449 crash_kexec_stop_spus();
450#if defined(CONFIG_PPC_STD_MMU_64) && defined(CONFIG_SMP)
451 crash_kexec_wait_realmode(crashing_cpu);
452#endif
415 if (ppc_md.kexec_cpu_down) 453 if (ppc_md.kexec_cpu_down)
416 ppc_md.kexec_cpu_down(1, 0); 454 ppc_md.kexec_cpu_down(1, 0);
417} 455}