diff options
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r-- | arch/powerpc/kernel/traps.c | 80 |
1 files changed, 55 insertions, 25 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index dcc6f159fd9..f7862224fe8 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -90,51 +90,80 @@ EXPORT_SYMBOL(unregister_die_notifier); * Trap & Exception support */ -static DEFINE_SPINLOCK(die_lock); +#ifdef CONFIG_PMAC_BACKLIGHT +static void pmac_backlight_unblank(void) +{ + mutex_lock(&pmac_backlight_mutex); + if (pmac_backlight) { + struct backlight_properties *props; + + props = &pmac_backlight->props; + props->brightness = props->max_brightness; + props->power = FB_BLANK_UNBLANK; + backlight_update_status(pmac_backlight); + } + mutex_unlock(&pmac_backlight_mutex); +} +#else +static inline void pmac_backlight_unblank(void) { } +#endif 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; - console_verbose(); - spin_lock_irq(&die_lock); - bust_spinlocks(1); -#ifdef CONFIG_PMAC_BACKLIGHT - mutex_lock(&pmac_backlight_mutex); - if (machine_is(powermac) && pmac_backlight) { - struct backlight_properties *props; + oops_enter(); - down(&pmac_backlight->sem); - props = pmac_backlight->props; - props->brightness = props->max_brightness; - props->power = FB_BLANK_UNBLANK; - props->update_status(pmac_backlight); - up(&pmac_backlight->sem); + 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); } - mutex_unlock(&pmac_backlight_mutex); -#endif - 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())) @@ -147,6 +176,7 @@ int die(const char *str, struct pt_regs *regs, long err) if (panic_on_oops) panic("Fatal exception"); + oops_exit(); do_exit(err); return 0; |