diff -urN a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt --- a/Documentation/kernel-parameters.txt 2012-01-05 08:55:44.000000000 +0900 +++ b/Documentation/kernel-parameters.txt 2012-01-07 17:55:17.000000000 +0900 @@ -1900,6 +1900,11 @@ timeout = 0: wait forever timeout < 0: reboot immediately Format: + panic_output= [KNL] Enable/disable the output devices of choice + panic_output=0: disable the signalling completely + panic_output=1: only blink the leds (the default) + panic_output=2: only beep + panic_output=3: do both parkbd.port= [HW] Parallel port number the keyboard adapter is connected to, default is 0. diff -urN a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c --- a/drivers/input/misc/pcspkr.c 2012-01-05 08:55:44.000000000 +0900 +++ b/drivers/input/misc/pcspkr.c 2012-01-07 17:55:17.000000000 +0900 @@ -63,6 +63,34 @@ return 0; } +/* + * pcspkr_panic_beep() will beep the PC speaker on or off and is called + * when kernel panics. Beeping a speaker is useful for users running X + * who may not see the console and will help distingushing panics from + * "real" lockups. + */ + +static void pcspkr_panic_beep(int value) +{ + unsigned int count = 0; + + if (value > 20 && value < 32767) + count = PIT_TICK_RATE / value; + + if (count) { + /* set command for counter 2, 2 byte write */ + outb_p(0xB6, 0x43); + /* select desired HZ */ + outb_p(count & 0xff, 0x42); + outb((count >> 8) & 0xff, 0x42); + /* enable counter 2 */ + outb_p(inb_p(0x61) | 3, 0x61); + } else { + /* disable counter 2 */ + outb(inb_p(0x61) & 0xFC, 0x61); + } +} + static int __devinit pcspkr_probe(struct platform_device *dev) { struct input_dev *pcspkr_dev; @@ -138,12 +166,16 @@ static int __init pcspkr_init(void) { + panic_beep = pcspkr_panic_beep; + return platform_driver_register(&pcspkr_platform_driver); } static void __exit pcspkr_exit(void) { platform_driver_unregister(&pcspkr_platform_driver); + + panic_beep = NULL; } module_init(pcspkr_init); diff -urN a/include/linux/kernel.h b/include/linux/kernel.h --- a/include/linux/kernel.h 2012-01-05 08:55:44.000000000 +0900 +++ b/include/linux/kernel.h 2012-01-07 17:55:17.000000000 +0900 @@ -185,6 +185,7 @@ extern struct atomic_notifier_head panic_notifier_list; extern long (*panic_blink)(int state); +extern void (*panic_beep)(int value); NORET_TYPE void panic(const char * fmt, ...) __attribute__ ((NORET_AND format (printf, 1, 2))) __cold; extern void oops_enter(void); diff -urN a/kernel/panic.c b/kernel/panic.c --- a/kernel/panic.c 2012-01-05 08:55:44.000000000 +0900 +++ b/kernel/panic.c 2012-01-07 17:55:17.000000000 +0900 @@ -24,8 +24,11 @@ #include #include +#define PANIC_OUTPUT_BLINK (1 << 0) +#define PANIC_OUTPUT_BEEP (1 << 1) #define PANIC_TIMER_STEP 100 -#define PANIC_BLINK_SPD 18 +#define PANIC_BLINK_SPD 12 +#define PANIC_BEEP_HZ 880 int panic_on_oops; static unsigned long tainted_mask; @@ -35,6 +38,7 @@ int panic_timeout; EXPORT_SYMBOL_GPL(panic_timeout); +static int panic_output = PANIC_OUTPUT_BLINK; ATOMIC_NOTIFIER_HEAD(panic_notifier_list); @@ -49,6 +53,13 @@ long (*panic_blink)(int state); EXPORT_SYMBOL(panic_blink); +static void no_beep(int value) +{ +} + +void (*panic_beep)(int value); +EXPORT_SYMBOL(panic_beep); + /** * panic - halt the system * @fmt: The text string to print @@ -103,6 +114,8 @@ if (!panic_blink) panic_blink = no_blink; + if (!panic_beep) + panic_beep = no_beep; if (panic_timeout > 0) { /* @@ -114,7 +127,11 @@ for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) { touch_nmi_watchdog(); if (i >= i_next) { - i += panic_blink(state ^= 1); + state ^= 1; + if (panic_output & PANIC_OUTPUT_BLINK) + i += panic_blink(state); + if (panic_output & PANIC_OUTPUT_BEEP) + panic_beep((state) ? PANIC_BEEP_HZ : 0); i_next = i + 3600 / PANIC_BLINK_SPD; } mdelay(PANIC_TIMER_STEP); @@ -148,7 +165,11 @@ for (i = 0; ; i += PANIC_TIMER_STEP) { touch_softlockup_watchdog(); if (i >= i_next) { - i += panic_blink(state ^= 1); + state ^= 1; + if (panic_output & PANIC_OUTPUT_BLINK) + i += panic_blink(state); + if (panic_output & PANIC_OUTPUT_BEEP) + panic_beep((state) ? PANIC_BEEP_HZ : 0); i_next = i + 3600 / PANIC_BLINK_SPD; } mdelay(PANIC_TIMER_STEP); @@ -436,6 +457,13 @@ #endif core_param(panic, panic_timeout, int, 0644); +/* "panic_output=0" disables the blinking as it caused problems with + * certain console switches. + * + * "panic_output | 1" does the show using kbd leds. + * "panic_output | 2" throws in beeping via panic_beep(). + */ +core_param(panic_output, panic_output, int, 0644); core_param(pause_on_oops, pause_on_oops, int, 0644); static int __init oops_setup(char *s)