aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/nmi.c28
-rw-r--r--arch/x86_64/kernel/nmi.c27
-rw-r--r--drivers/acpi/namespace/nsinit.c9
-rw-r--r--include/linux/nmi.h9
4 files changed, 72 insertions, 1 deletions
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 7d3f4e22d6fb..b11abacc5cfd 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -383,6 +383,34 @@ void enable_timer_nmi_watchdog(void)
383 } 383 }
384} 384}
385 385
386static void __acpi_nmi_disable(void *__unused)
387{
388 apic_write_around(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
389}
390
391/*
392 * Disable timer based NMIs on all CPUs:
393 */
394void acpi_nmi_disable(void)
395{
396 if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
397 on_each_cpu(__acpi_nmi_disable, NULL, 0, 1);
398}
399
400static void __acpi_nmi_enable(void *__unused)
401{
402 apic_write_around(APIC_LVT0, APIC_DM_NMI);
403}
404
405/*
406 * Enable timer based NMIs on all CPUs:
407 */
408void acpi_nmi_enable(void)
409{
410 if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
411 on_each_cpu(__acpi_nmi_enable, NULL, 0, 1);
412}
413
386#ifdef CONFIG_PM 414#ifdef CONFIG_PM
387 415
388static int nmi_pm_active; /* nmi_active before suspend */ 416static int nmi_pm_active; /* nmi_active before suspend */
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index e59cda134166..269fe585e71e 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -368,6 +368,33 @@ void enable_timer_nmi_watchdog(void)
368 } 368 }
369} 369}
370 370
371static void __acpi_nmi_disable(void *__unused)
372{
373 apic_write(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
374}
375
376/*
377 * Disable timer based NMIs on all CPUs:
378 */
379void acpi_nmi_disable(void)
380{
381 if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
382 on_each_cpu(__acpi_nmi_disable, NULL, 0, 1);
383}
384
385static void __acpi_nmi_enable(void *__unused)
386{
387 apic_write(APIC_LVT0, APIC_DM_NMI);
388}
389
390/*
391 * Enable timer based NMIs on all CPUs:
392 */
393void acpi_nmi_enable(void)
394{
395 if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
396 on_each_cpu(__acpi_nmi_enable, NULL, 0, 1);
397}
371#ifdef CONFIG_PM 398#ifdef CONFIG_PM
372 399
373static int nmi_pm_active; /* nmi_active before suspend */ 400static int nmi_pm_active; /* nmi_active before suspend */
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index 326af8fc0ce7..33db2241044e 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -45,6 +45,7 @@
45#include <acpi/acnamesp.h> 45#include <acpi/acnamesp.h>
46#include <acpi/acdispat.h> 46#include <acpi/acdispat.h>
47#include <acpi/acinterp.h> 47#include <acpi/acinterp.h>
48#include <linux/nmi.h>
48 49
49#define _COMPONENT ACPI_NAMESPACE 50#define _COMPONENT ACPI_NAMESPACE
50ACPI_MODULE_NAME("nsinit") 51ACPI_MODULE_NAME("nsinit")
@@ -534,7 +535,15 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
534 info->parameter_type = ACPI_PARAM_ARGS; 535 info->parameter_type = ACPI_PARAM_ARGS;
535 info->flags = ACPI_IGNORE_RETURN_VALUE; 536 info->flags = ACPI_IGNORE_RETURN_VALUE;
536 537
538 /*
539 * Some hardware relies on this being executed as atomically
540 * as possible (without an NMI being received in the middle of
541 * this) - so disable NMIs and initialize the device:
542 */
543 acpi_nmi_disable();
537 status = acpi_ns_evaluate(info); 544 status = acpi_ns_evaluate(info);
545 acpi_nmi_enable();
546
538 if (ACPI_SUCCESS(status)) { 547 if (ACPI_SUCCESS(status)) {
539 walk_info->num_INI++; 548 walk_info->num_INI++;
540 549
diff --git a/include/linux/nmi.h b/include/linux/nmi.h
index acb4ed130247..29af2d5df097 100644
--- a/include/linux/nmi.h
+++ b/include/linux/nmi.h
@@ -17,8 +17,15 @@
17#ifdef ARCH_HAS_NMI_WATCHDOG 17#ifdef ARCH_HAS_NMI_WATCHDOG
18#include <asm/nmi.h> 18#include <asm/nmi.h>
19extern void touch_nmi_watchdog(void); 19extern void touch_nmi_watchdog(void);
20extern void acpi_nmi_disable(void);
21extern void acpi_nmi_enable(void);
20#else 22#else
21# define touch_nmi_watchdog() touch_softlockup_watchdog() 23static inline void touch_nmi_watchdog(void)
24{
25 touch_softlockup_watchdog();
26}
27static inline void acpi_nmi_disable(void) { }
28static inline void acpi_nmi_enable(void) { }
22#endif 29#endif
23 30
24#ifndef trigger_all_cpu_backtrace 31#ifndef trigger_all_cpu_backtrace