[PATCH] Add panic blinking to 2.6

From: Andi Kleen
Date: Sat Oct 30 2004 - 20:40:12 EST



This patch readds the panic blinking that was in 2.4
to 2.6. This is useful to see when you're in X that the
machine has paniced

It addresses previously criticism.
It should work now when the keyboard interrupt is off.
It doesn't fully emulate the handler, but has a timeout
for this case.

Signed-off-by: Andi Kleen <ak@xxxxxxx>

diff -u linux-2.6.9-work/drivers/input/serio/i8042.c-PANIC linux-2.6.9-work/drivers/input/serio/i8042.c
--- linux-2.6.9-work/drivers/input/serio/i8042.c-PANIC 2004-10-19 01:55:13.000000000 +0200
+++ linux-2.6.9-work/drivers/input/serio/i8042.c 2004-10-20 05:20:24.000000000 +0200
@@ -887,6 +887,41 @@
0
};

+static int blink_frequency = 500;
+module_param_named(panicblink, blink_frequency, int, 0600);
+
+/* Catch the case when the kbd interrupt is off */
+#define DELAY do { mdelay(1); if (++delay > 10) return delay; } while(0)
+
+/* Tell the user who may be running in X and not see the console that we have
+ panic'ed. This is to distingush panics from "real" lockups. */
+static long i8042_panic_blink(long count)
+{
+ long delay = 0;
+ static long last_blink;
+ static char led;
+ /* Roughly 1/2s frequency. KDB uses about 1s. Make sure it is
+ different. */
+ if (!blink_frequency)
+ return 0;
+ if (count - last_blink < blink_frequency)
+ return 0;
+ led ^= 0x01 | 0x04;
+ while (i8042_read_status() & I8042_STR_IBF)
+ DELAY;
+ i8042_write_data(0xed); /* set leds */
+ DELAY;
+ while (i8042_read_status() & I8042_STR_IBF)
+ DELAY;
+ DELAY;
+ i8042_write_data(led);
+ DELAY;
+ last_blink = count;
+ return delay;
+}
+
+#undef DELAY
+
/*
* Suspend/resume handlers for the new PM scheme (driver model)
*/
@@ -1047,6 +1082,8 @@

register_reboot_notifier(&i8042_notifier);

+ panic_blink = i8042_panic_blink;
+
return 0;
}

@@ -1077,6 +1114,8 @@
driver_unregister(&i8042_driver);

i8042_platform_exit();
+
+ panic_blink = NULL;
}

module_init(i8042_init);
diff -u linux-2.6.9-work/include/linux/kernel.h-PANIC linux-2.6.9-work/include/linux/kernel.h
--- linux-2.6.9-work/include/linux/kernel.h-PANIC 2004-10-19 01:55:35.000000000 +0200
+++ linux-2.6.9-work/include/linux/kernel.h 2004-10-20 05:17:55.000000000 +0200
@@ -66,6 +66,7 @@
})

extern struct notifier_block *panic_notifier_list;
+extern long (*panic_blink)(long time);
NORET_TYPE void panic(const char * fmt, ...)
__attribute__ ((NORET_AND format (printf, 1, 2)));
asmlinkage NORET_TYPE void do_exit(long error_code)
diff -u linux-2.6.9-work/kernel/panic.c-PANIC linux-2.6.9-work/kernel/panic.c
--- linux-2.6.9-work/kernel/panic.c-PANIC 2004-10-19 01:55:36.000000000 +0200
+++ linux-2.6.9-work/kernel/panic.c 2004-10-20 05:17:55.000000000 +0200
@@ -37,6 +37,15 @@
}
__setup("panic=", panic_setup);

+static long no_blink(long time)
+{
+ return 0;
+}
+
+/* Returns how long it waited in ms */
+long (*panic_blink)(long time) = no_blink;
+EXPORT_SYMBOL(panic_blink);
+
/**
* panic - halt the system
* @fmt: The text string to print
@@ -49,6 +58,7 @@

NORET_TYPE void panic(const char * fmt, ...)
{
+ long i;
static char buf[1024];
va_list args;
#if defined(CONFIG_ARCH_S390)
@@ -70,15 +80,16 @@

if (panic_timeout > 0)
{
- int i;
/*
* Delay timeout seconds before rebooting the machine.
* We can't use the "normal" timers since we just panicked..
*/
printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout);
- for (i = 0; i < panic_timeout; i++) {
+ for (i = 0; i < panic_timeout*1000; ) {
touch_nmi_watchdog();
- mdelay(1000);
+ i += panic_blink(i);
+ mdelay(1);
+ i++;
}
/*
* Should we run the reboot notifier. For the moment Im
@@ -99,8 +110,11 @@
disabled_wait(caller);
#endif
local_irq_enable();
- for (;;)
- ;
+ for (i = 0;;) {
+ i += panic_blink(i);
+ mdelay(1);
+ i++;
+ }
}

EXPORT_SYMBOL(panic);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/