diff options
| author | Don Zickus <dzickus@redhat.com> | 2010-02-12 17:19:19 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2010-02-14 03:19:43 -0500 |
| commit | 504d7cf10ee42bb76b9556859f23d4121dee0a77 (patch) | |
| tree | edaa43a7c221f0926d150dbbeb38abc5fe0f1cc6 /kernel | |
| parent | c3128fb6ad39b0edda6675d20585a64846cf89ea (diff) | |
nmi_watchdog: Compile and portability fixes
The original patch was x86_64 centric. Changed the code to make
it less so.
ested by building and running on a powerpc.
Signed-off-by: Don Zickus <dzickus@redhat.com>
Cc: peterz@infradead.org
Cc: gorcunov@gmail.com
Cc: aris@redhat.com
LKML-Reference: <1266013161-31197-2-git-send-email-dzickus@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/nmi_watchdog.c | 52 | ||||
| -rw-r--r-- | kernel/sysctl.c | 15 |
2 files changed, 55 insertions, 12 deletions
diff --git a/kernel/nmi_watchdog.c b/kernel/nmi_watchdog.c index 36817b214d69..73c1954a97bb 100644 --- a/kernel/nmi_watchdog.c +++ b/kernel/nmi_watchdog.c | |||
| @@ -30,6 +30,8 @@ static DEFINE_PER_CPU(struct perf_event *, nmi_watchdog_ev); | |||
| 30 | static DEFINE_PER_CPU(int, nmi_watchdog_touch); | 30 | static DEFINE_PER_CPU(int, nmi_watchdog_touch); |
| 31 | static DEFINE_PER_CPU(long, alert_counter); | 31 | static DEFINE_PER_CPU(long, alert_counter); |
| 32 | 32 | ||
| 33 | static int panic_on_timeout; | ||
| 34 | |||
| 33 | void touch_nmi_watchdog(void) | 35 | void touch_nmi_watchdog(void) |
| 34 | { | 36 | { |
| 35 | __raw_get_cpu_var(nmi_watchdog_touch) = 1; | 37 | __raw_get_cpu_var(nmi_watchdog_touch) = 1; |
| @@ -46,19 +48,49 @@ void touch_all_nmi_watchdog(void) | |||
| 46 | touch_softlockup_watchdog(); | 48 | touch_softlockup_watchdog(); |
| 47 | } | 49 | } |
| 48 | 50 | ||
| 51 | static int __init setup_nmi_watchdog(char *str) | ||
| 52 | { | ||
| 53 | if (!strncmp(str, "panic", 5)) { | ||
| 54 | panic_on_timeout = 1; | ||
| 55 | str = strchr(str, ','); | ||
| 56 | if (!str) | ||
| 57 | return 1; | ||
| 58 | ++str; | ||
| 59 | } | ||
| 60 | return 1; | ||
| 61 | } | ||
| 62 | __setup("nmi_watchdog=", setup_nmi_watchdog); | ||
| 63 | |||
| 49 | #ifdef CONFIG_SYSCTL | 64 | #ifdef CONFIG_SYSCTL |
| 50 | /* | 65 | /* |
| 51 | * proc handler for /proc/sys/kernel/nmi_watchdog | 66 | * proc handler for /proc/sys/kernel/nmi_watchdog |
| 52 | */ | 67 | */ |
| 68 | int nmi_watchdog_enabled; | ||
| 69 | |||
| 53 | int proc_nmi_enabled(struct ctl_table *table, int write, | 70 | int proc_nmi_enabled(struct ctl_table *table, int write, |
| 54 | void __user *buffer, size_t *length, loff_t *ppos) | 71 | void __user *buffer, size_t *length, loff_t *ppos) |
| 55 | { | 72 | { |
| 56 | int cpu; | 73 | int cpu; |
| 57 | 74 | ||
| 58 | if (per_cpu(nmi_watchdog_ev, smp_processor_id()) == NULL) | 75 | if (!write) { |
| 76 | struct perf_event *event; | ||
| 77 | for_each_online_cpu(cpu) { | ||
| 78 | event = per_cpu(nmi_watchdog_ev, cpu); | ||
| 79 | if (event->state > PERF_EVENT_STATE_OFF) { | ||
| 80 | nmi_watchdog_enabled = 1; | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | proc_dointvec(table, write, buffer, length, ppos); | ||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | if (per_cpu(nmi_watchdog_ev, smp_processor_id()) == NULL) { | ||
| 59 | nmi_watchdog_enabled = 0; | 89 | nmi_watchdog_enabled = 0; |
| 60 | else | 90 | proc_dointvec(table, write, buffer, length, ppos); |
| 61 | nmi_watchdog_enabled = 1; | 91 | printk("NMI watchdog failed configuration, can not be enabled\n"); |
| 92 | return 0; | ||
| 93 | } | ||
| 62 | 94 | ||
| 63 | touch_all_nmi_watchdog(); | 95 | touch_all_nmi_watchdog(); |
| 64 | proc_dointvec(table, write, buffer, length, ppos); | 96 | proc_dointvec(table, write, buffer, length, ppos); |
| @@ -81,8 +113,6 @@ struct perf_event_attr wd_attr = { | |||
| 81 | .disabled = 1, | 113 | .disabled = 1, |
| 82 | }; | 114 | }; |
| 83 | 115 | ||
| 84 | static int panic_on_timeout; | ||
| 85 | |||
| 86 | void wd_overflow(struct perf_event *event, int nmi, | 116 | void wd_overflow(struct perf_event *event, int nmi, |
| 87 | struct perf_sample_data *data, | 117 | struct perf_sample_data *data, |
| 88 | struct pt_regs *regs) | 118 | struct pt_regs *regs) |
| @@ -103,11 +133,11 @@ void wd_overflow(struct perf_event *event, int nmi, | |||
| 103 | */ | 133 | */ |
| 104 | per_cpu(alert_counter,cpu) += 1; | 134 | per_cpu(alert_counter,cpu) += 1; |
| 105 | if (per_cpu(alert_counter,cpu) == 5) { | 135 | if (per_cpu(alert_counter,cpu) == 5) { |
| 106 | /* | 136 | if (panic_on_timeout) { |
| 107 | * die_nmi will return ONLY if NOTIFY_STOP happens.. | 137 | panic("NMI Watchdog detected LOCKUP on cpu %d", cpu); |
| 108 | */ | 138 | } else { |
| 109 | die_nmi("BUG: NMI Watchdog detected LOCKUP", | 139 | WARN(1, "NMI Watchdog detected LOCKUP on cpu %d", cpu); |
| 110 | regs, panic_on_timeout); | 140 | } |
| 111 | } | 141 | } |
| 112 | } else { | 142 | } else { |
| 113 | per_cpu(alert_counter,cpu) = 0; | 143 | per_cpu(alert_counter,cpu) = 0; |
| @@ -133,7 +163,7 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) | |||
| 133 | case CPU_ONLINE: | 163 | case CPU_ONLINE: |
| 134 | case CPU_ONLINE_FROZEN: | 164 | case CPU_ONLINE_FROZEN: |
| 135 | /* originally wanted the below chunk to be in CPU_UP_PREPARE, but caps is unpriv for non-CPU0 */ | 165 | /* originally wanted the below chunk to be in CPU_UP_PREPARE, but caps is unpriv for non-CPU0 */ |
| 136 | wd_attr.sample_period = cpu_khz * 1000; | 166 | wd_attr.sample_period = hw_nmi_get_sample_period(); |
| 137 | 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); |
| 138 | if (IS_ERR(event)) { | 168 | if (IS_ERR(event)) { |
| 139 | printk(KERN_ERR "nmi watchdog failed to create perf event on %i: %p\n", hotcpu, event); | 169 | printk(KERN_ERR "nmi watchdog failed to create perf event on %i: %p\n", hotcpu, event); |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 8a68b2448468..ac72c9e6bd9b 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -60,6 +60,10 @@ | |||
| 60 | #include <asm/io.h> | 60 | #include <asm/io.h> |
| 61 | #endif | 61 | #endif |
| 62 | 62 | ||
| 63 | #ifdef CONFIG_NMI_WATCHDOG | ||
| 64 | #include <linux/nmi.h> | ||
| 65 | #endif | ||
| 66 | |||
| 63 | 67 | ||
| 64 | #if defined(CONFIG_SYSCTL) | 68 | #if defined(CONFIG_SYSCTL) |
| 65 | 69 | ||
| @@ -692,7 +696,16 @@ static struct ctl_table kern_table[] = { | |||
| 692 | .mode = 0444, | 696 | .mode = 0444, |
| 693 | .proc_handler = proc_dointvec, | 697 | .proc_handler = proc_dointvec, |
| 694 | }, | 698 | }, |
| 695 | #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) | 699 | #if defined(CONFIG_NMI_WATCHDOG) |
| 700 | { | ||
| 701 | .procname = "nmi_watchdog", | ||
| 702 | .data = &nmi_watchdog_enabled, | ||
| 703 | .maxlen = sizeof (int), | ||
| 704 | .mode = 0644, | ||
| 705 | .proc_handler = proc_nmi_enabled, | ||
| 706 | }, | ||
| 707 | #endif | ||
| 708 | #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) && !defined(CONFIG_NMI_WATCHDOG) | ||
| 696 | { | 709 | { |
| 697 | .procname = "unknown_nmi_panic", | 710 | .procname = "unknown_nmi_panic", |
| 698 | .data = &unknown_nmi_panic, | 711 | .data = &unknown_nmi_panic, |
