diff options
author | Don Zickus <dzickus@redhat.com> | 2010-02-16 17:02:25 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-02-17 02:16:02 -0500 |
commit | 96ca4028aca0638d0e11dcbfabc4283054072933 (patch) | |
tree | b2619a48be22d4af020cf49e6e740ca16481b7b7 | |
parent | 6081b6cd9702967889de34fe5da1f96bb96d0ab8 (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.c | 23 |
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 | ||
64 | struct perf_event_attr wd_attr = { | 64 | struct 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 | ||
72 | struct 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 | |||
72 | void wd_overflow(struct perf_event *event, int nmi, | 80 | void 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, | |||
105 | static int enable_nmi_watchdog(int cpu) | 113 | static 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; |