diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/kernel/crash.c | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index d446755..b942980 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -30,6 +30,20 @@ #include <asm/system.h> #include <asm/setjmp.h> +/* + * The primary CPU waits a while for all secondary CPUs to enter. This is to + * avoid sending an IPI if the secondary CPUs are entering + * crash_kexec_secondary on their own (eg via a system reset). + * + * The secondary timeout has to be longer than the primary. Both timeouts are + * in milliseconds. + */ +#define PRIMARY_TIMEOUT 500 +#define SECONDARY_TIMEOUT 1000 + +#define IPI_TIMEOUT 10000 +#define REAL_MODE_TIMEOUT 10000 + /* This keeps a track of which one is the crashing cpu. */ int crashing_cpu = -1; static cpumask_t cpus_in_crash = CPU_MASK_NONE; @@ -99,11 +113,9 @@ again: * FIXME: Until we will have the way to stop other CPUs reliably, * the crash CPU will send an IPI and wait for other CPUs to * respond. - * Delay of at least 10 seconds. */ - msecs = 10000; + msecs = IPI_TIMEOUT; while ((cpumask_weight(&cpus_in_crash) < ncpus) && (--msecs > 0)) { - cpu_relax(); mdelay(1); } @@ -163,11 +175,11 @@ again: void crash_kexec_secondary(struct pt_regs *regs) { unsigned long flags; - int msecs = 500; + int msecs = SECONDARY_TIMEOUT; local_irq_save(flags); - /* Wait 500ms for the primary crash CPU to signal its progress */ + /* Wait for the primary crash CPU to signal its progress */ while (crashing_cpu < 0) { if (--msecs < 0) { /* No response, kdump image may not have been loaded */ @@ -176,7 +188,6 @@ void crash_kexec_secondary(struct pt_regs *regs) } mdelay(1); - cpu_relax(); } crash_ipi_callback(regs); @@ -211,7 +222,7 @@ static void crash_kexec_wait_realmode(int cpu) unsigned int msecs; int i; - msecs = 10000; + msecs = REAL_MODE_TIMEOUT; for (i=0; i < nr_cpu_ids && msecs > 0; i++) { if (i == cpu) continue; @@ -306,6 +317,14 @@ void default_machine_crash_shutdown(struct pt_regs *regs) */ crashing_cpu = smp_processor_id(); crash_save_cpu(regs, crashing_cpu); + + /* + * If we came in via system reset, wait a while for the secondary + * CPUs to enter. + */ + if (TRAP(regs) == 0x100) + mdelay(PRIMARY_TIMEOUT); + crash_kexec_prepare_cpus(crashing_cpu); cpumask_set_cpu(crashing_cpu, &cpus_in_crash); crash_kexec_wait_realmode(crashing_cpu); |