diff options
Diffstat (limited to 'kernel/watchdog.c')
-rw-r--r-- | kernel/watchdog.c | 50 |
1 files changed, 26 insertions, 24 deletions
diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 6e3c41a4024c..d7ebdf4cea98 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c | |||
@@ -57,6 +57,8 @@ static int __init hardlockup_panic_setup(char *str) | |||
57 | { | 57 | { |
58 | if (!strncmp(str, "panic", 5)) | 58 | if (!strncmp(str, "panic", 5)) |
59 | hardlockup_panic = 1; | 59 | hardlockup_panic = 1; |
60 | else if (!strncmp(str, "0", 1)) | ||
61 | no_watchdog = 1; | ||
60 | return 1; | 62 | return 1; |
61 | } | 63 | } |
62 | __setup("nmi_watchdog=", hardlockup_panic_setup); | 64 | __setup("nmi_watchdog=", hardlockup_panic_setup); |
@@ -116,12 +118,12 @@ static void __touch_watchdog(void) | |||
116 | { | 118 | { |
117 | int this_cpu = smp_processor_id(); | 119 | int this_cpu = smp_processor_id(); |
118 | 120 | ||
119 | __get_cpu_var(watchdog_touch_ts) = get_timestamp(this_cpu); | 121 | __this_cpu_write(watchdog_touch_ts, get_timestamp(this_cpu)); |
120 | } | 122 | } |
121 | 123 | ||
122 | void touch_softlockup_watchdog(void) | 124 | void touch_softlockup_watchdog(void) |
123 | { | 125 | { |
124 | __raw_get_cpu_var(watchdog_touch_ts) = 0; | 126 | __this_cpu_write(watchdog_touch_ts, 0); |
125 | } | 127 | } |
126 | EXPORT_SYMBOL(touch_softlockup_watchdog); | 128 | EXPORT_SYMBOL(touch_softlockup_watchdog); |
127 | 129 | ||
@@ -165,12 +167,12 @@ void touch_softlockup_watchdog_sync(void) | |||
165 | /* watchdog detector functions */ | 167 | /* watchdog detector functions */ |
166 | static int is_hardlockup(void) | 168 | static int is_hardlockup(void) |
167 | { | 169 | { |
168 | unsigned long hrint = __get_cpu_var(hrtimer_interrupts); | 170 | unsigned long hrint = __this_cpu_read(hrtimer_interrupts); |
169 | 171 | ||
170 | if (__get_cpu_var(hrtimer_interrupts_saved) == hrint) | 172 | if (__this_cpu_read(hrtimer_interrupts_saved) == hrint) |
171 | return 1; | 173 | return 1; |
172 | 174 | ||
173 | __get_cpu_var(hrtimer_interrupts_saved) = hrint; | 175 | __this_cpu_write(hrtimer_interrupts_saved, hrint); |
174 | return 0; | 176 | return 0; |
175 | } | 177 | } |
176 | #endif | 178 | #endif |
@@ -203,8 +205,8 @@ static void watchdog_overflow_callback(struct perf_event *event, int nmi, | |||
203 | /* Ensure the watchdog never gets throttled */ | 205 | /* Ensure the watchdog never gets throttled */ |
204 | event->hw.interrupts = 0; | 206 | event->hw.interrupts = 0; |
205 | 207 | ||
206 | if (__get_cpu_var(watchdog_nmi_touch) == true) { | 208 | if (__this_cpu_read(watchdog_nmi_touch) == true) { |
207 | __get_cpu_var(watchdog_nmi_touch) = false; | 209 | __this_cpu_write(watchdog_nmi_touch, false); |
208 | return; | 210 | return; |
209 | } | 211 | } |
210 | 212 | ||
@@ -218,7 +220,7 @@ static void watchdog_overflow_callback(struct perf_event *event, int nmi, | |||
218 | int this_cpu = smp_processor_id(); | 220 | int this_cpu = smp_processor_id(); |
219 | 221 | ||
220 | /* only print hardlockups once */ | 222 | /* only print hardlockups once */ |
221 | if (__get_cpu_var(hard_watchdog_warn) == true) | 223 | if (__this_cpu_read(hard_watchdog_warn) == true) |
222 | return; | 224 | return; |
223 | 225 | ||
224 | if (hardlockup_panic) | 226 | if (hardlockup_panic) |
@@ -226,16 +228,16 @@ static void watchdog_overflow_callback(struct perf_event *event, int nmi, | |||
226 | else | 228 | else |
227 | WARN(1, "Watchdog detected hard LOCKUP on cpu %d", this_cpu); | 229 | WARN(1, "Watchdog detected hard LOCKUP on cpu %d", this_cpu); |
228 | 230 | ||
229 | __get_cpu_var(hard_watchdog_warn) = true; | 231 | __this_cpu_write(hard_watchdog_warn, true); |
230 | return; | 232 | return; |
231 | } | 233 | } |
232 | 234 | ||
233 | __get_cpu_var(hard_watchdog_warn) = false; | 235 | __this_cpu_write(hard_watchdog_warn, false); |
234 | return; | 236 | return; |
235 | } | 237 | } |
236 | static void watchdog_interrupt_count(void) | 238 | static void watchdog_interrupt_count(void) |
237 | { | 239 | { |
238 | __get_cpu_var(hrtimer_interrupts)++; | 240 | __this_cpu_inc(hrtimer_interrupts); |
239 | } | 241 | } |
240 | #else | 242 | #else |
241 | static inline void watchdog_interrupt_count(void) { return; } | 243 | static inline void watchdog_interrupt_count(void) { return; } |
@@ -244,7 +246,7 @@ static inline void watchdog_interrupt_count(void) { return; } | |||
244 | /* watchdog kicker functions */ | 246 | /* watchdog kicker functions */ |
245 | static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) | 247 | static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) |
246 | { | 248 | { |
247 | unsigned long touch_ts = __get_cpu_var(watchdog_touch_ts); | 249 | unsigned long touch_ts = __this_cpu_read(watchdog_touch_ts); |
248 | struct pt_regs *regs = get_irq_regs(); | 250 | struct pt_regs *regs = get_irq_regs(); |
249 | int duration; | 251 | int duration; |
250 | 252 | ||
@@ -252,18 +254,18 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) | |||
252 | watchdog_interrupt_count(); | 254 | watchdog_interrupt_count(); |
253 | 255 | ||
254 | /* kick the softlockup detector */ | 256 | /* kick the softlockup detector */ |
255 | wake_up_process(__get_cpu_var(softlockup_watchdog)); | 257 | wake_up_process(__this_cpu_read(softlockup_watchdog)); |
256 | 258 | ||
257 | /* .. and repeat */ | 259 | /* .. and repeat */ |
258 | hrtimer_forward_now(hrtimer, ns_to_ktime(get_sample_period())); | 260 | hrtimer_forward_now(hrtimer, ns_to_ktime(get_sample_period())); |
259 | 261 | ||
260 | if (touch_ts == 0) { | 262 | if (touch_ts == 0) { |
261 | if (unlikely(__get_cpu_var(softlockup_touch_sync))) { | 263 | if (unlikely(__this_cpu_read(softlockup_touch_sync))) { |
262 | /* | 264 | /* |
263 | * If the time stamp was touched atomically | 265 | * If the time stamp was touched atomically |
264 | * make sure the scheduler tick is up to date. | 266 | * make sure the scheduler tick is up to date. |
265 | */ | 267 | */ |
266 | __get_cpu_var(softlockup_touch_sync) = false; | 268 | __this_cpu_write(softlockup_touch_sync, false); |
267 | sched_clock_tick(); | 269 | sched_clock_tick(); |
268 | } | 270 | } |
269 | __touch_watchdog(); | 271 | __touch_watchdog(); |
@@ -279,7 +281,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) | |||
279 | duration = is_softlockup(touch_ts); | 281 | duration = is_softlockup(touch_ts); |
280 | if (unlikely(duration)) { | 282 | if (unlikely(duration)) { |
281 | /* only warn once */ | 283 | /* only warn once */ |
282 | if (__get_cpu_var(soft_watchdog_warn) == true) | 284 | if (__this_cpu_read(soft_watchdog_warn) == true) |
283 | return HRTIMER_RESTART; | 285 | return HRTIMER_RESTART; |
284 | 286 | ||
285 | printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", | 287 | printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", |
@@ -294,9 +296,9 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) | |||
294 | 296 | ||
295 | if (softlockup_panic) | 297 | if (softlockup_panic) |
296 | panic("softlockup: hung tasks"); | 298 | panic("softlockup: hung tasks"); |
297 | __get_cpu_var(soft_watchdog_warn) = true; | 299 | __this_cpu_write(soft_watchdog_warn, true); |
298 | } else | 300 | } else |
299 | __get_cpu_var(soft_watchdog_warn) = false; | 301 | __this_cpu_write(soft_watchdog_warn, false); |
300 | 302 | ||
301 | return HRTIMER_RESTART; | 303 | return HRTIMER_RESTART; |
302 | } | 304 | } |
@@ -307,7 +309,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) | |||
307 | */ | 309 | */ |
308 | static int watchdog(void *unused) | 310 | static int watchdog(void *unused) |
309 | { | 311 | { |
310 | struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; | 312 | static struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; |
311 | struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); | 313 | struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); |
312 | 314 | ||
313 | sched_setscheduler(current, SCHED_FIFO, ¶m); | 315 | sched_setscheduler(current, SCHED_FIFO, ¶m); |
@@ -364,7 +366,8 @@ static int watchdog_nmi_enable(int cpu) | |||
364 | goto out_save; | 366 | goto out_save; |
365 | } | 367 | } |
366 | 368 | ||
367 | printk(KERN_ERR "NMI watchdog failed to create perf event on cpu%i: %p\n", cpu, event); | 369 | printk(KERN_ERR "NMI watchdog disabled for cpu%i: unable to create perf event: %ld\n", |
370 | cpu, PTR_ERR(event)); | ||
368 | return PTR_ERR(event); | 371 | return PTR_ERR(event); |
369 | 372 | ||
370 | /* success path */ | 373 | /* success path */ |
@@ -547,13 +550,13 @@ static struct notifier_block __cpuinitdata cpu_nfb = { | |||
547 | .notifier_call = cpu_callback | 550 | .notifier_call = cpu_callback |
548 | }; | 551 | }; |
549 | 552 | ||
550 | static int __init spawn_watchdog_task(void) | 553 | void __init lockup_detector_init(void) |
551 | { | 554 | { |
552 | void *cpu = (void *)(long)smp_processor_id(); | 555 | void *cpu = (void *)(long)smp_processor_id(); |
553 | int err; | 556 | int err; |
554 | 557 | ||
555 | if (no_watchdog) | 558 | if (no_watchdog) |
556 | return 0; | 559 | return; |
557 | 560 | ||
558 | err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu); | 561 | err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu); |
559 | WARN_ON(notifier_to_errno(err)); | 562 | WARN_ON(notifier_to_errno(err)); |
@@ -561,6 +564,5 @@ static int __init spawn_watchdog_task(void) | |||
561 | cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); | 564 | cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); |
562 | register_cpu_notifier(&cpu_nfb); | 565 | register_cpu_notifier(&cpu_nfb); |
563 | 566 | ||
564 | return 0; | 567 | return; |
565 | } | 568 | } |
566 | early_initcall(spawn_watchdog_task); | ||