Pull percpu-dtc into release branch
[pandora-kernel.git] / arch / powerpc / kernel / traps.c
index dcc6f15..f786222 100644 (file)
@@ -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;