aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDon Zickus <dzickus@redhat.com>2010-02-12 17:19:20 -0500
committerIngo Molnar <mingo@elte.hu>2010-02-14 03:19:44 -0500
commitcf454aecb31741a0438ed1201b3dd153c7c7b19a (patch)
tree99fd901681e220f7a94575c908417ea6d8ca38ed
parent504d7cf10ee42bb76b9556859f23d4121dee0a77 (diff)
nmi_watchdog: Fallback to software events when no hardware pmu detected
Not all arches have a PMU or have perf_event support for their PMU. The nmi_watchdog will fail in those cases. Fallback to using software events to generate nmi_watchdog traffic with local apic interrupts. Tested on a Pentium4 and it worked as expected, excepting for detecting cpu lockups. The problem with using software events as a cpu lock up detector is the nmi_watchdog uses the logic that if local apic interrupts stop incrementing then the cpu is probably locked up. But with software events we use the local apic to trigger the nmi_watchdog callback to see if local apic interrupts are still firing, which obviously they are otherwise we wouldn't have been triggered. The algorithm to detect cpu lock ups is the same as the old nmi_watchdog. Perhaps we need to find a better way to detect lock ups? Signed-off-by: Don Zickus <dzickus@redhat.com> Cc: peterz@infradead.org Cc: gorcunov@gmail.com Cc: aris@redhat.com LKML-Reference: <1266013161-31197-3-git-send-email-dzickus@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--kernel/nmi_watchdog.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/kernel/nmi_watchdog.c b/kernel/nmi_watchdog.c
index 73c1954a97bb..4f23505d887d 100644
--- a/kernel/nmi_watchdog.c
+++ b/kernel/nmi_watchdog.c
@@ -166,8 +166,12 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
166 wd_attr.sample_period = hw_nmi_get_sample_period(); 166 wd_attr.sample_period = hw_nmi_get_sample_period();
167 event = perf_event_create_kernel_counter(&wd_attr, hotcpu, -1, wd_overflow); 167 event = perf_event_create_kernel_counter(&wd_attr, hotcpu, -1, wd_overflow);
168 if (IS_ERR(event)) { 168 if (IS_ERR(event)) {
169 printk(KERN_ERR "nmi watchdog failed to create perf event on %i: %p\n", hotcpu, event); 169 wd_attr.type = PERF_TYPE_SOFTWARE;
170 return NOTIFY_BAD; 170 event = perf_event_create_kernel_counter(&wd_attr, hotcpu, -1, wd_overflow);
171 if (IS_ERR(event)) {
172 printk(KERN_ERR "nmi watchdog failed to create perf event on %i: %p\n", hotcpu, event);
173 return NOTIFY_BAD;
174 }
171 } 175 }
172 per_cpu(nmi_watchdog_ev, hotcpu) = event; 176 per_cpu(nmi_watchdog_ev, hotcpu) = event;
173 perf_event_enable(per_cpu(nmi_watchdog_ev, hotcpu)); 177 perf_event_enable(per_cpu(nmi_watchdog_ev, hotcpu));