diff options
Diffstat (limited to 'arch/sparc/kernel/nmi.c')
-rw-r--r-- | arch/sparc/kernel/nmi.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c index a9973bb4a1b2..95e73c63c99d 100644 --- a/arch/sparc/kernel/nmi.c +++ b/arch/sparc/kernel/nmi.c | |||
@@ -42,7 +42,7 @@ static int panic_on_timeout; | |||
42 | */ | 42 | */ |
43 | atomic_t nmi_active = ATOMIC_INIT(0); /* oprofile uses this */ | 43 | atomic_t nmi_active = ATOMIC_INIT(0); /* oprofile uses this */ |
44 | EXPORT_SYMBOL(nmi_active); | 44 | EXPORT_SYMBOL(nmi_active); |
45 | 45 | static int nmi_init_done; | |
46 | static unsigned int nmi_hz = HZ; | 46 | static unsigned int nmi_hz = HZ; |
47 | static DEFINE_PER_CPU(short, wd_enabled); | 47 | static DEFINE_PER_CPU(short, wd_enabled); |
48 | static int endflag __initdata; | 48 | static int endflag __initdata; |
@@ -153,6 +153,8 @@ static void report_broken_nmi(int cpu, int *prev_nmi_count) | |||
153 | 153 | ||
154 | void stop_nmi_watchdog(void *unused) | 154 | void stop_nmi_watchdog(void *unused) |
155 | { | 155 | { |
156 | if (!__this_cpu_read(wd_enabled)) | ||
157 | return; | ||
156 | pcr_ops->write_pcr(0, pcr_ops->pcr_nmi_disable); | 158 | pcr_ops->write_pcr(0, pcr_ops->pcr_nmi_disable); |
157 | __this_cpu_write(wd_enabled, 0); | 159 | __this_cpu_write(wd_enabled, 0); |
158 | atomic_dec(&nmi_active); | 160 | atomic_dec(&nmi_active); |
@@ -207,6 +209,9 @@ error: | |||
207 | 209 | ||
208 | void start_nmi_watchdog(void *unused) | 210 | void start_nmi_watchdog(void *unused) |
209 | { | 211 | { |
212 | if (__this_cpu_read(wd_enabled)) | ||
213 | return; | ||
214 | |||
210 | __this_cpu_write(wd_enabled, 1); | 215 | __this_cpu_write(wd_enabled, 1); |
211 | atomic_inc(&nmi_active); | 216 | atomic_inc(&nmi_active); |
212 | 217 | ||
@@ -259,6 +264,8 @@ int __init nmi_init(void) | |||
259 | } | 264 | } |
260 | } | 265 | } |
261 | 266 | ||
267 | nmi_init_done = 1; | ||
268 | |||
262 | return err; | 269 | return err; |
263 | } | 270 | } |
264 | 271 | ||
@@ -270,3 +277,38 @@ static int __init setup_nmi_watchdog(char *str) | |||
270 | return 0; | 277 | return 0; |
271 | } | 278 | } |
272 | __setup("nmi_watchdog=", setup_nmi_watchdog); | 279 | __setup("nmi_watchdog=", setup_nmi_watchdog); |
280 | |||
281 | /* | ||
282 | * sparc specific NMI watchdog enable function. | ||
283 | * Enables watchdog if it is not enabled already. | ||
284 | */ | ||
285 | int watchdog_nmi_enable(unsigned int cpu) | ||
286 | { | ||
287 | if (atomic_read(&nmi_active) == -1) { | ||
288 | pr_warn("NMI watchdog cannot be enabled or disabled\n"); | ||
289 | return -1; | ||
290 | } | ||
291 | |||
292 | /* | ||
293 | * watchdog thread could start even before nmi_init is called. | ||
294 | * Just Return in that case. Let nmi_init finish the init | ||
295 | * process first. | ||
296 | */ | ||
297 | if (!nmi_init_done) | ||
298 | return 0; | ||
299 | |||
300 | smp_call_function_single(cpu, start_nmi_watchdog, NULL, 1); | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | /* | ||
305 | * sparc specific NMI watchdog disable function. | ||
306 | * Disables watchdog if it is not disabled already. | ||
307 | */ | ||
308 | void watchdog_nmi_disable(unsigned int cpu) | ||
309 | { | ||
310 | if (atomic_read(&nmi_active) == -1) | ||
311 | pr_warn_once("NMI watchdog cannot be enabled or disabled\n"); | ||
312 | else | ||
313 | smp_call_function_single(cpu, stop_nmi_watchdog, NULL, 1); | ||
314 | } | ||