diff options
-rw-r--r-- | arch/i386/kernel/nmi.c | 28 | ||||
-rw-r--r-- | arch/x86_64/kernel/nmi.c | 27 | ||||
-rw-r--r-- | drivers/acpi/namespace/nsinit.c | 9 | ||||
-rw-r--r-- | include/linux/nmi.h | 9 |
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 | ||
386 | static 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 | */ | ||
394 | void 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 | |||
400 | static 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 | */ | ||
408 | void 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 | ||
388 | static int nmi_pm_active; /* nmi_active before suspend */ | 416 | static 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 | ||
371 | static 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 | */ | ||
379 | void 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 | |||
385 | static 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 | */ | ||
393 | void 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 | ||
373 | static int nmi_pm_active; /* nmi_active before suspend */ | 400 | static 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 |
50 | ACPI_MODULE_NAME("nsinit") | 51 | ACPI_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> |
19 | extern void touch_nmi_watchdog(void); | 19 | extern void touch_nmi_watchdog(void); |
20 | extern void acpi_nmi_disable(void); | ||
21 | extern void acpi_nmi_enable(void); | ||
20 | #else | 22 | #else |
21 | # define touch_nmi_watchdog() touch_softlockup_watchdog() | 23 | static inline void touch_nmi_watchdog(void) |
24 | { | ||
25 | touch_softlockup_watchdog(); | ||
26 | } | ||
27 | static inline void acpi_nmi_disable(void) { } | ||
28 | static inline void acpi_nmi_enable(void) { } | ||
22 | #endif | 29 | #endif |
23 | 30 | ||
24 | #ifndef trigger_all_cpu_backtrace | 31 | #ifndef trigger_all_cpu_backtrace |