aboutsummaryrefslogtreecommitdiff
path: root/kernel/watchdog.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/watchdog.c')
-rw-r--r--kernel/watchdog.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 70bf11815f84..64f44cfb3bdc 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -248,6 +248,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,
@@ -281,13 +283,21 @@ static void watchdog_overflow_callback(struct perf_event *event,
/* only print hardlockups once */
if (__this_cpu_read(hard_watchdog_warn) == true)
return;
+ /*
+ * If early-printk is enabled then make sure we do not
+ * lock up in printk() and kill console logging:
+ */
+ printk_kill();
- if (hardlockup_panic)
+ 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;
@@ -430,6 +440,7 @@ static void watchdog_enable(unsigned int cpu)
/* kick off the timer for the hardlockup detector */
hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer->function = watchdog_timer_fn;
+ hrtimer->irqsafe = 1;
/* Enable the perf event */
watchdog_nmi_enable(cpu);