Commit 99d4a6c9 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[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: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 99770da7
...@@ -813,6 +813,41 @@ void i8042_controller_cleanup(void) ...@@ -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 * Here we try to restore the original BIOS settings
*/ */
...@@ -863,6 +898,8 @@ static int i8042_controller_resume(void) ...@@ -863,6 +898,8 @@ static int i8042_controller_resume(void)
*/ */
mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
panic_blink = i8042_panic_blink;
return 0; return 0;
} }
...@@ -1077,6 +1114,8 @@ void __exit i8042_exit(void) ...@@ -1077,6 +1114,8 @@ void __exit i8042_exit(void)
driver_unregister(&i8042_driver); driver_unregister(&i8042_driver);
i8042_platform_exit(); i8042_platform_exit();
panic_blink = NULL;
} }
module_init(i8042_init); module_init(i8042_init);
......
...@@ -66,6 +66,7 @@ void __might_sleep(char *file, int line); ...@@ -66,6 +66,7 @@ void __might_sleep(char *file, int line);
}) })
extern struct notifier_block *panic_notifier_list; extern struct notifier_block *panic_notifier_list;
extern long (*panic_blink)(long time);
NORET_TYPE void panic(const char * fmt, ...) NORET_TYPE void panic(const char * fmt, ...)
__attribute__ ((NORET_AND format (printf, 1, 2))); __attribute__ ((NORET_AND format (printf, 1, 2)));
asmlinkage NORET_TYPE void do_exit(long error_code) asmlinkage NORET_TYPE void do_exit(long error_code)
......
...@@ -36,6 +36,15 @@ static int __init panic_setup(char *str) ...@@ -36,6 +36,15 @@ static int __init panic_setup(char *str)
} }
__setup("panic=", panic_setup); __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 * panic - halt the system
* @fmt: The text string to print * @fmt: The text string to print
...@@ -48,6 +57,7 @@ __setup("panic=", panic_setup); ...@@ -48,6 +57,7 @@ __setup("panic=", panic_setup);
NORET_TYPE void panic(const char * fmt, ...) NORET_TYPE void panic(const char * fmt, ...)
{ {
long i;
static char buf[1024]; static char buf[1024];
va_list args; va_list args;
#if defined(CONFIG_ARCH_S390) #if defined(CONFIG_ARCH_S390)
...@@ -69,15 +79,16 @@ NORET_TYPE void panic(const char * fmt, ...) ...@@ -69,15 +79,16 @@ NORET_TYPE void panic(const char * fmt, ...)
if (panic_timeout > 0) if (panic_timeout > 0)
{ {
int i;
/* /*
* Delay timeout seconds before rebooting the machine. * Delay timeout seconds before rebooting the machine.
* We can't use the "normal" timers since we just panicked.. * We can't use the "normal" timers since we just panicked..
*/ */
printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout); 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(); touch_nmi_watchdog();
mdelay(1000); i += panic_blink(i);
mdelay(1);
i++;
} }
/* /*
* Should we run the reboot notifier. For the moment Im * Should we run the reboot notifier. For the moment Im
...@@ -98,8 +109,11 @@ NORET_TYPE void panic(const char * fmt, ...) ...@@ -98,8 +109,11 @@ NORET_TYPE void panic(const char * fmt, ...)
disabled_wait(caller); disabled_wait(caller);
#endif #endif
local_irq_enable(); local_irq_enable();
for (;;) for (i = 0;;) {
; i += panic_blink(i);
mdelay(1);
i++;
}
} }
EXPORT_SYMBOL(panic); EXPORT_SYMBOL(panic);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment