summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2011-11-30 00:23:09 (GMT)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-12-08 03:02:22 (GMT)
commit58154c8ce71a7854d969d73468fd00e5eeeab708 (patch)
tree42833866181659098501fd9ecce6cd1e333bd434
parentfaa8bf8878636e40646d307e0516dbadb3b65b4f (diff)
downloadlinux-fsl-qoriq-58154c8ce71a7854d969d73468fd00e5eeeab708.tar.xz
powerpc: Give us time to get all oopses out before panicking
I've been seeing truncated output when people send system reset info to me. We should see a backtrace for every CPU, but the panic() code takes the box down before they all make it out to the console. The panic code runs unlocked so we also see corrupted console output. If we are going to panic, then delay 1 second before calling into the panic code. Move oops_exit inside the die lock and put a newline between oopses for clarity. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/kernel/traps.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 5459d14..9137787 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -158,6 +158,8 @@ int die(const char *str, struct pt_regs *regs, long err)
bust_spinlocks(0);
die.lock_owner = -1;
add_taint(TAINT_DIE);
+ oops_exit();
+ printk("\n");
raw_spin_unlock_irqrestore(&die.lock, flags);
if (kexec_should_crash(current) ||
@@ -165,13 +167,23 @@ int die(const char *str, struct pt_regs *regs, long err)
crash_kexec(regs);
crash_kexec_secondary(regs);
+ /*
+ * While our oops output is serialised by a spinlock, output
+ * from panic() called below can race and corrupt it. If we
+ * know we are going to panic, delay for 1 second so we have a
+ * chance to get clean backtraces from all CPUs that are oopsing.
+ */
+ if (in_interrupt() || panic_on_oops || !current->pid ||
+ is_global_init(current)) {
+ mdelay(MSEC_PER_SEC);
+ }
+
if (in_interrupt())
panic("Fatal exception in interrupt");
if (panic_on_oops)
panic("Fatal exception");
- oops_exit();
do_exit(err);
return 0;