diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-07-22 15:58:40 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-10 00:18:47 (GMT) |
commit | 765986731ec002f5608d3bd3d4a093b645fb40ed (patch) | |
tree | 85466fc349252d0cc6d9e9ded25b29d9e21919ee /kernel | |
parent | 017907f4541930de79139fbcbcd2c4b0bbea4e10 (diff) | |
download | linux-fsl-qoriq-765986731ec002f5608d3bd3d4a093b645fb40ed.tar.xz |
printk-kill.patch
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/printk/printk.c | 79 | ||||
-rw-r--r-- | kernel/watchdog.c | 15 |
2 files changed, 69 insertions, 25 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index b4e8500..68e3f1a 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1488,6 +1488,55 @@ static size_t cont_print_text(char *text, size_t size) return textlen; } +#ifdef CONFIG_EARLY_PRINTK +struct console *early_console; + +void early_vprintk(const char *fmt, va_list ap) +{ + if (early_console) { + char buf[512]; + int n = vscnprintf(buf, sizeof(buf), fmt, ap); + + early_console->write(early_console, buf, n); + } +} + +asmlinkage void early_printk(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + early_vprintk(fmt, ap); + va_end(ap); +} + +/* + * This is independent of any log levels - a global + * kill switch that turns off all of printk. + * + * Used by the NMI watchdog if early-printk is enabled. + */ +static bool __read_mostly printk_killswitch; + +void printk_kill(void) +{ + printk_killswitch = true; +} + +static int forced_early_printk(const char *fmt, va_list ap) +{ + if (!printk_killswitch) + return 0; + early_vprintk(fmt, ap); + return 1; +} +#else +static inline int forced_early_printk(const char *fmt, va_list ap) +{ + return 0; +} +#endif + asmlinkage int vprintk_emit(int facility, int level, const char *dict, size_t dictlen, const char *fmt, va_list args) @@ -1501,6 +1550,13 @@ asmlinkage int vprintk_emit(int facility, int level, int this_cpu; int printed_len = 0; + /* + * Fall back to early_printk if a debugging subsystem has + * killed printk output + */ + if (unlikely(forced_early_printk(fmt, args))) + return 1; + boot_delay_msec(level); printk_delay(); @@ -1723,29 +1779,6 @@ static size_t cont_print_text(char *text, size_t size) { return 0; } #endif /* CONFIG_PRINTK */ -#ifdef CONFIG_EARLY_PRINTK -struct console *early_console; - -void early_vprintk(const char *fmt, va_list ap) -{ - if (early_console) { - char buf[512]; - int n = vscnprintf(buf, sizeof(buf), fmt, ap); - - early_console->write(early_console, buf, n); - } -} - -asmlinkage void early_printk(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - early_vprintk(fmt, ap); - va_end(ap); -} -#endif - static int __add_preferred_console(char *name, int idx, char *options, char *brl_options) { diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 4431610..cbad091 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -205,6 +205,8 @@ static int is_softlockup(unsigned long touch_ts) #ifdef CONFIG_HARDLOCKUP_DETECTOR +static DEFINE_RAW_SPINLOCK(watchdog_output_lock); + static struct perf_event_attr wd_hw_attr = { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES, @@ -239,10 +241,19 @@ static void watchdog_overflow_callback(struct perf_event *event, if (__this_cpu_read(hard_watchdog_warn) == true) return; - if (hardlockup_panic) + /* + * If early-printk is enabled then make sure we do not + * lock up in printk() and kill console logging: + */ + printk_kill(); + + if (hardlockup_panic) { panic("Watchdog detected hard LOCKUP on cpu %d", this_cpu); - else + } else { + raw_spin_lock(&watchdog_output_lock); WARN(1, "Watchdog detected hard LOCKUP on cpu %d", this_cpu); + raw_spin_unlock(&watchdog_output_lock); + } __this_cpu_write(hard_watchdog_warn, true); return; |