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; |
