aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/crash.c
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2011-11-29 19:23:16 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-12-07 22:02:24 -0500
commit549e88a134b3b393a4312e8d76628b9260eee57f (patch)
tree753fbc597df1b3771e75aa5fa75867c1a0672f45 /arch/powerpc/kernel/crash.c
parent90e8f57cf873188bc5cff445059ddeb72dc51d8c (diff)
powerpc/kdump: Delay before sending IPI on a system reset
If we enter the kdump code via system reset, wait a bit before sending the IPI to capture all secondary CPUs. Without it we race with the hypervisor that is issuing the system reset to each CPU. If the IPI gets there first the system reset oops output then shows the register state of the IPI handler which is not what we want. I took the opportunity to add defines for all the various delays we have. There's no need for cpu_relax when we are doing an mdelay, so remove them too. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/crash.c')
-rw-r--r--arch/powerpc/kernel/crash.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index d4467557b00e..b942980e9650 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -30,6 +30,20 @@
30#include <asm/system.h> 30#include <asm/system.h>
31#include <asm/setjmp.h> 31#include <asm/setjmp.h>
32 32
33/*
34 * The primary CPU waits a while for all secondary CPUs to enter. This is to
35 * avoid sending an IPI if the secondary CPUs are entering
36 * crash_kexec_secondary on their own (eg via a system reset).
37 *
38 * The secondary timeout has to be longer than the primary. Both timeouts are
39 * in milliseconds.
40 */
41#define PRIMARY_TIMEOUT 500
42#define SECONDARY_TIMEOUT 1000
43
44#define IPI_TIMEOUT 10000
45#define REAL_MODE_TIMEOUT 10000
46
33/* This keeps a track of which one is the crashing cpu. */ 47/* This keeps a track of which one is the crashing cpu. */
34int crashing_cpu = -1; 48int crashing_cpu = -1;
35static cpumask_t cpus_in_crash = CPU_MASK_NONE; 49static cpumask_t cpus_in_crash = CPU_MASK_NONE;
@@ -99,11 +113,9 @@ again:
99 * FIXME: Until we will have the way to stop other CPUs reliably, 113 * FIXME: Until we will have the way to stop other CPUs reliably,
100 * the crash CPU will send an IPI and wait for other CPUs to 114 * the crash CPU will send an IPI and wait for other CPUs to
101 * respond. 115 * respond.
102 * Delay of at least 10 seconds.
103 */ 116 */
104 msecs = 10000; 117 msecs = IPI_TIMEOUT;
105 while ((cpumask_weight(&cpus_in_crash) < ncpus) && (--msecs > 0)) { 118 while ((cpumask_weight(&cpus_in_crash) < ncpus) && (--msecs > 0)) {
106 cpu_relax();
107 mdelay(1); 119 mdelay(1);
108 } 120 }
109 121
@@ -163,11 +175,11 @@ again:
163void crash_kexec_secondary(struct pt_regs *regs) 175void crash_kexec_secondary(struct pt_regs *regs)
164{ 176{
165 unsigned long flags; 177 unsigned long flags;
166 int msecs = 500; 178 int msecs = SECONDARY_TIMEOUT;
167 179
168 local_irq_save(flags); 180 local_irq_save(flags);
169 181
170 /* Wait 500ms for the primary crash CPU to signal its progress */ 182 /* Wait for the primary crash CPU to signal its progress */
171 while (crashing_cpu < 0) { 183 while (crashing_cpu < 0) {
172 if (--msecs < 0) { 184 if (--msecs < 0) {
173 /* No response, kdump image may not have been loaded */ 185 /* No response, kdump image may not have been loaded */
@@ -176,7 +188,6 @@ void crash_kexec_secondary(struct pt_regs *regs)
176 } 188 }
177 189
178 mdelay(1); 190 mdelay(1);
179 cpu_relax();
180 } 191 }
181 192
182 crash_ipi_callback(regs); 193 crash_ipi_callback(regs);
@@ -211,7 +222,7 @@ static void crash_kexec_wait_realmode(int cpu)
211 unsigned int msecs; 222 unsigned int msecs;
212 int i; 223 int i;
213 224
214 msecs = 10000; 225 msecs = REAL_MODE_TIMEOUT;
215 for (i=0; i < nr_cpu_ids && msecs > 0; i++) { 226 for (i=0; i < nr_cpu_ids && msecs > 0; i++) {
216 if (i == cpu) 227 if (i == cpu)
217 continue; 228 continue;
@@ -306,6 +317,14 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
306 */ 317 */
307 crashing_cpu = smp_processor_id(); 318 crashing_cpu = smp_processor_id();
308 crash_save_cpu(regs, crashing_cpu); 319 crash_save_cpu(regs, crashing_cpu);
320
321 /*
322 * If we came in via system reset, wait a while for the secondary
323 * CPUs to enter.
324 */
325 if (TRAP(regs) == 0x100)
326 mdelay(PRIMARY_TIMEOUT);
327
309 crash_kexec_prepare_cpus(crashing_cpu); 328 crash_kexec_prepare_cpus(crashing_cpu);
310 cpumask_set_cpu(crashing_cpu, &cpus_in_crash); 329 cpumask_set_cpu(crashing_cpu, &cpus_in_crash);
311 crash_kexec_wait_realmode(crashing_cpu); 330 crash_kexec_wait_realmode(crashing_cpu);