diff options
| author | Andi Kleen <ak@suse.de> | 2004-11-01 23:07:18 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-11-01 23:07:18 -0800 |
| commit | 99d4a6c9b95b3b83f275d64a2e59643a55b68ce0 (patch) | |
| tree | 0f91548099c46df5484fb3905f2278c945e28b4f | |
| parent | 99770da703ef1cbe32376aaa1b945af80acd3c82 (diff) | |
[PATCH] Add panic blinking to 2.6
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@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | drivers/input/serio/i8042.c | 39 | ||||
| -rw-r--r-- | include/linux/kernel.h | 1 | ||||
| -rw-r--r-- | kernel/panic.c | 24 |
3 files changed, 59 insertions, 5 deletions
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 151c29ddb635..6730e1ae08f8 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -813,6 +813,41 @@ void i8042_controller_cleanup(void) } +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 + /* * Here we try to restore the original BIOS settings */ @@ -863,6 +898,8 @@ static int i8042_controller_resume(void) */ mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); + panic_blink = i8042_panic_blink; + return 0; } @@ -1077,6 +1114,8 @@ void __exit i8042_exit(void) driver_unregister(&i8042_driver); i8042_platform_exit(); + + panic_blink = NULL; } module_init(i8042_init); diff --git a/include/linux/kernel.h b/include/linux/kernel.h index cf2f984e1b95..8723ac62ddd7 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -66,6 +66,7 @@ void __might_sleep(char *file, int line); }) 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 --git a/kernel/panic.c b/kernel/panic.c index c7ab9981c7aa..97918d4ff44f 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -36,6 +36,15 @@ static int __init panic_setup(char *str) } __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 @@ -48,6 +57,7 @@ __setup("panic=", panic_setup); NORET_TYPE void panic(const char * fmt, ...) { + long i; static char buf[1024]; va_list args; #if defined(CONFIG_ARCH_S390) @@ -69,15 +79,16 @@ NORET_TYPE void panic(const char * fmt, ...) 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 @@ -98,8 +109,11 @@ NORET_TYPE void panic(const char * fmt, ...) disabled_wait(caller); #endif local_irq_enable(); - for (;;) - ; + for (i = 0;;) { + i += panic_blink(i); + mdelay(1); + i++; + } } EXPORT_SYMBOL(panic); |
