aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDon Zickus <dzickus@redhat.com>2010-02-16 17:02:25 -0500
committerIngo Molnar <mingo@elte.hu>2010-02-17 02:16:02 -0500
commit96ca4028aca0638d0e11dcbfabc4283054072933 (patch)
treeb2619a48be22d4af020cf49e6e740ca16481b7b7
parent6081b6cd9702967889de34fe5da1f96bb96d0ab8 (diff)
nmi_watchdog: Properly configure for software events
Paul Mackerras brought up a good point that when fallbacking to software events, I may have been lucky in my configuration. Modified the code to explicit provide a new configuration for software events. Suggested-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Don Zickus <dzickus@redhat.com> Cc: gorcunov@gmail.com Cc: aris@redhat.com Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <1266357745-26671-1-git-send-email-dzickus@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--kernel/nmi_watchdog.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/kernel/nmi_watchdog.c b/kernel/nmi_watchdog.c
index 633b230c2319..3c75cbf3acb8 100644
--- a/kernel/nmi_watchdog.c
+++ b/kernel/nmi_watchdog.c
@@ -61,7 +61,7 @@ static int __init setup_nmi_watchdog(char *str)
61} 61}
62__setup("nmi_watchdog=", setup_nmi_watchdog); 62__setup("nmi_watchdog=", setup_nmi_watchdog);
63 63
64struct perf_event_attr wd_attr = { 64struct perf_event_attr wd_hw_attr = {
65 .type = PERF_TYPE_HARDWARE, 65 .type = PERF_TYPE_HARDWARE,
66 .config = PERF_COUNT_HW_CPU_CYCLES, 66 .config = PERF_COUNT_HW_CPU_CYCLES,
67 .size = sizeof(struct perf_event_attr), 67 .size = sizeof(struct perf_event_attr),
@@ -69,6 +69,14 @@ struct perf_event_attr wd_attr = {
69 .disabled = 1, 69 .disabled = 1,
70}; 70};
71 71
72struct perf_event_attr wd_sw_attr = {
73 .type = PERF_TYPE_SOFTWARE,
74 .config = PERF_COUNT_SW_CPU_CLOCK,
75 .size = sizeof(struct perf_event_attr),
76 .pinned = 1,
77 .disabled = 1,
78};
79
72void wd_overflow(struct perf_event *event, int nmi, 80void wd_overflow(struct perf_event *event, int nmi,
73 struct perf_sample_data *data, 81 struct perf_sample_data *data,
74 struct pt_regs *regs) 82 struct pt_regs *regs)
@@ -105,6 +113,7 @@ void wd_overflow(struct perf_event *event, int nmi,
105static int enable_nmi_watchdog(int cpu) 113static int enable_nmi_watchdog(int cpu)
106{ 114{
107 struct perf_event *event; 115 struct perf_event *event;
116 struct perf_event_attr *wd_attr;
108 117
109 event = per_cpu(nmi_watchdog_ev, cpu); 118 event = per_cpu(nmi_watchdog_ev, cpu);
110 if (event && event->state > PERF_EVENT_STATE_OFF) 119 if (event && event->state > PERF_EVENT_STATE_OFF)
@@ -112,11 +121,15 @@ static int enable_nmi_watchdog(int cpu)
112 121
113 if (event == NULL) { 122 if (event == NULL) {
114 /* Try to register using hardware perf events first */ 123 /* Try to register using hardware perf events first */
115 wd_attr.sample_period = hw_nmi_get_sample_period(); 124 wd_attr = &wd_hw_attr;
116 event = perf_event_create_kernel_counter(&wd_attr, cpu, -1, wd_overflow); 125 wd_attr->sample_period = hw_nmi_get_sample_period();
126 event = perf_event_create_kernel_counter(wd_attr, cpu, -1, wd_overflow);
117 if (IS_ERR(event)) { 127 if (IS_ERR(event)) {
118 wd_attr.type = PERF_TYPE_SOFTWARE; 128 /* hardware doesn't exist or not supported, fallback to software events */
119 event = perf_event_create_kernel_counter(&wd_attr, cpu, -1, wd_overflow); 129 printk("nmi_watchdog: hardware not available, trying software events\n");
130 wd_attr = &wd_sw_attr;
131 wd_attr->sample_period = NSEC_PER_SEC;
132 event = perf_event_create_kernel_counter(wd_attr, cpu, -1, wd_overflow);
120 if (IS_ERR(event)) { 133 if (IS_ERR(event)) {
121 printk(KERN_ERR "nmi watchdog failed to create perf event on %i: %p\n", cpu, event); 134 printk(KERN_ERR "nmi watchdog failed to create perf event on %i: %p\n", cpu, event);
122 return -1; 135 return -1;