aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/nmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/nmi.c')
-rw-r--r--arch/x86/kernel/nmi.c43
1 files changed, 36 insertions, 7 deletions
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
index 2c97f07f1c2c..13316cf57cdb 100644
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -131,6 +131,11 @@ static void report_broken_nmi(int cpu, int *prev_nmi_count)
131 atomic_dec(&nmi_active); 131 atomic_dec(&nmi_active);
132} 132}
133 133
134static void __acpi_nmi_disable(void *__unused)
135{
136 apic_write(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
137}
138
134int __init check_nmi_watchdog(void) 139int __init check_nmi_watchdog(void)
135{ 140{
136 unsigned int *prev_nmi_count; 141 unsigned int *prev_nmi_count;
@@ -179,8 +184,12 @@ int __init check_nmi_watchdog(void)
179 kfree(prev_nmi_count); 184 kfree(prev_nmi_count);
180 return 0; 185 return 0;
181error: 186error:
182 if (nmi_watchdog == NMI_IO_APIC && !timer_through_8259) 187 if (nmi_watchdog == NMI_IO_APIC) {
183 disable_8259A_irq(0); 188 if (!timer_through_8259)
189 disable_8259A_irq(0);
190 on_each_cpu(__acpi_nmi_disable, NULL, 1);
191 }
192
184#ifdef CONFIG_X86_32 193#ifdef CONFIG_X86_32
185 timer_ack = 0; 194 timer_ack = 0;
186#endif 195#endif
@@ -285,11 +294,6 @@ void acpi_nmi_enable(void)
285 on_each_cpu(__acpi_nmi_enable, NULL, 1); 294 on_each_cpu(__acpi_nmi_enable, NULL, 1);
286} 295}
287 296
288static void __acpi_nmi_disable(void *__unused)
289{
290 apic_write(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
291}
292
293/* 297/*
294 * Disable timer based NMIs on all CPUs: 298 * Disable timer based NMIs on all CPUs:
295 */ 299 */
@@ -340,6 +344,8 @@ void stop_apic_nmi_watchdog(void *unused)
340 return; 344 return;
341 if (nmi_watchdog == NMI_LOCAL_APIC) 345 if (nmi_watchdog == NMI_LOCAL_APIC)
342 lapic_watchdog_stop(); 346 lapic_watchdog_stop();
347 else
348 __acpi_nmi_disable(NULL);
343 __get_cpu_var(wd_enabled) = 0; 349 __get_cpu_var(wd_enabled) = 0;
344 atomic_dec(&nmi_active); 350 atomic_dec(&nmi_active);
345} 351}
@@ -465,6 +471,24 @@ nmi_watchdog_tick(struct pt_regs *regs, unsigned reason)
465 471
466#ifdef CONFIG_SYSCTL 472#ifdef CONFIG_SYSCTL
467 473
474static void enable_ioapic_nmi_watchdog_single(void *unused)
475{
476 __get_cpu_var(wd_enabled) = 1;
477 atomic_inc(&nmi_active);
478 __acpi_nmi_enable(NULL);
479}
480
481static void enable_ioapic_nmi_watchdog(void)
482{
483 on_each_cpu(enable_ioapic_nmi_watchdog_single, NULL, 1);
484 touch_nmi_watchdog();
485}
486
487static void disable_ioapic_nmi_watchdog(void)
488{
489 on_each_cpu(stop_apic_nmi_watchdog, NULL, 1);
490}
491
468static int __init setup_unknown_nmi_panic(char *str) 492static int __init setup_unknown_nmi_panic(char *str)
469{ 493{
470 unknown_nmi_panic = 1; 494 unknown_nmi_panic = 1;
@@ -507,6 +531,11 @@ int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file,
507 enable_lapic_nmi_watchdog(); 531 enable_lapic_nmi_watchdog();
508 else 532 else
509 disable_lapic_nmi_watchdog(); 533 disable_lapic_nmi_watchdog();
534 } else if (nmi_watchdog == NMI_IO_APIC) {
535 if (nmi_watchdog_enabled)
536 enable_ioapic_nmi_watchdog();
537 else
538 disable_ioapic_nmi_watchdog();
510 } else { 539 } else {
511 printk(KERN_WARNING 540 printk(KERN_WARNING
512 "NMI watchdog doesn't know what hardware to touch\n"); 541 "NMI watchdog doesn't know what hardware to touch\n");