summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/traps.c
diff options
context:
space:
mode:
authoranton@samba.org <anton@samba.org>2007-03-21 02:38:13 +0100
committerPaul Mackerras <paulus@samba.org>2007-03-26 04:34:30 +0200
commit34c2a14fc20e4ab878fbf87e5f7fe1cff6afb3d4 (patch)
tree4af304129787a7873c03d114226dd2af9ef3ded1 /arch/powerpc/kernel/traps.c
parent[POWERPC] Clean up pmac_backlight_unblank in oops path (diff)
downloadlinux-34c2a14fc20e4ab878fbf87e5f7fe1cff6afb3d4.tar.xz
linux-34c2a14fc20e4ab878fbf87e5f7fe1cff6afb3d4.zip
[POWERPC] Handle recursive oopses
Handle recursive oopses, like on x86. We had a few cases recently where we locked up in oops printing and didnt make it into crashdump. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r--arch/powerpc/kernel/traps.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 6297da743db9..55d221ffcf1e 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -108,42 +108,62 @@ static void pmac_backlight_unblank(void)
static inline void pmac_backlight_unblank(void) { }
#endif
-static DEFINE_SPINLOCK(die_lock);
-
int die(const char *str, struct pt_regs *regs, long err)
{
+ static struct {
+ spinlock_t lock;
+ u32 lock_owner;
+ int lock_owner_depth;
+ } die = {
+ .lock = __SPIN_LOCK_UNLOCKED(die.lock),
+ .lock_owner = -1,
+ .lock_owner_depth = 0
+ };
static int die_counter;
+ unsigned long flags;
if (debugger(regs))
return 1;
oops_enter();
- console_verbose();
- spin_lock_irq(&die_lock);
- bust_spinlocks(1);
- if (machine_is(powermac))
- pmac_backlight_unblank();
+ if (die.lock_owner != raw_smp_processor_id()) {
+ console_verbose();
+ spin_lock_irqsave(&die.lock, flags);
+ die.lock_owner = smp_processor_id();
+ die.lock_owner_depth = 0;
+ bust_spinlocks(1);
+ if (machine_is(powermac))
+ pmac_backlight_unblank();
+ } else {
+ local_save_flags(flags);
+ }
- printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
+ if (++die.lock_owner_depth < 3) {
+ printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
#ifdef CONFIG_PREEMPT
- printk("PREEMPT ");
+ printk("PREEMPT ");
#endif
#ifdef CONFIG_SMP
- printk("SMP NR_CPUS=%d ", NR_CPUS);
+ printk("SMP NR_CPUS=%d ", NR_CPUS);
#endif
#ifdef CONFIG_DEBUG_PAGEALLOC
- printk("DEBUG_PAGEALLOC ");
+ printk("DEBUG_PAGEALLOC ");
#endif
#ifdef CONFIG_NUMA
- printk("NUMA ");
+ printk("NUMA ");
#endif
- printk("%s\n", ppc_md.name ? "" : ppc_md.name);
+ printk("%s\n", ppc_md.name ? "" : ppc_md.name);
+
+ print_modules();
+ show_regs(regs);
+ } else {
+ printk("Recursive die() failure, output suppressed\n");
+ }
- print_modules();
- show_regs(regs);
bust_spinlocks(0);
- spin_unlock_irq(&die_lock);
+ die.lock_owner = -1;
+ spin_unlock_irqrestore(&die.lock, flags);
if (kexec_should_crash(current) ||
kexec_sr_activated(smp_processor_id()))