summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2004-11-01 23:07:18 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-11-01 23:07:18 -0800
commit99d4a6c9b95b3b83f275d64a2e59643a55b68ce0 (patch)
tree0f91548099c46df5484fb3905f2278c945e28b4f
parent99770da703ef1cbe32376aaa1b945af80acd3c82 (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.c39
-rw-r--r--include/linux/kernel.h1
-rw-r--r--kernel/panic.c24
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);