From: Don Zickus Makes the start/stop paths of nmi watchdog more robust to handle the suspend/resume cases more gracefully. Signed-off-by: Don Zickus Cc: Shaohua Li Cc: Andi Kleen Signed-off-by: Andrew Morton --- arch/i386/kernel/nmi.c | 19 +++++++++++++++++-- arch/x86_64/kernel/nmi.c | 19 +++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff -puN arch/i386/kernel/nmi.c~x86-nmi-fix-2 arch/i386/kernel/nmi.c --- devel/arch/i386/kernel/nmi.c~x86-nmi-fix-2 2006-06-09 00:42:52.000000000 -0700 +++ devel-akpm/arch/i386/kernel/nmi.c 2006-06-09 00:42:52.000000000 -0700 @@ -744,11 +744,21 @@ static void stop_intel_arch_watchdog(voi void setup_apic_nmi_watchdog (void *unused) { + struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); + /* only support LOCAL and IO APICs for now */ if ((nmi_watchdog != NMI_LOCAL_APIC) && (nmi_watchdog != NMI_IO_APIC)) return; + if (wd->enabled == 1) + return; + + /* cheap hack to support suspend/resume */ + /* if cpu0 is not active neither should the other cpus */ + if ((smp_processor_id() != 0) && (atomic_read(&nmi_active) <= 0)) + return; + if (nmi_watchdog == NMI_LOCAL_APIC) { switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: @@ -786,17 +796,22 @@ void setup_apic_nmi_watchdog (void *unus return; } } - __get_cpu_var(nmi_watchdog_ctlblk.enabled) = 1; + wd->enabled = 1; atomic_inc(&nmi_active); } void stop_apic_nmi_watchdog(void *unused) { + struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); + /* only support LOCAL and IO APICs for now */ if ((nmi_watchdog != NMI_LOCAL_APIC) && (nmi_watchdog != NMI_IO_APIC)) return; + if (wd->enabled == 0) + return; + if (nmi_watchdog == NMI_LOCAL_APIC) { switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: @@ -824,7 +839,7 @@ void stop_apic_nmi_watchdog(void *unused return; } } - __get_cpu_var(nmi_watchdog_ctlblk.enabled) = 0; + wd->enabled = 0; atomic_dec(&nmi_active); } diff -puN arch/x86_64/kernel/nmi.c~x86-nmi-fix-2 arch/x86_64/kernel/nmi.c --- devel/arch/x86_64/kernel/nmi.c~x86-nmi-fix-2 2006-06-09 00:42:52.000000000 -0700 +++ devel-akpm/arch/x86_64/kernel/nmi.c 2006-06-09 00:42:52.000000000 -0700 @@ -671,11 +671,21 @@ static void stop_intel_arch_watchdog(voi void setup_apic_nmi_watchdog(void *unused) { + struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); + /* only support LOCAL and IO APICs for now */ if ((nmi_watchdog != NMI_LOCAL_APIC) && (nmi_watchdog != NMI_IO_APIC)) return; + if (wd->enabled == 1) + return; + + /* cheap hack to support suspend/resume */ + /* if cpu0 is not active neither should the other cpus */ + if ((smp_processor_id() != 0) && (atomic_read(&nmi_active) <= 0)) + return; + if (nmi_watchdog == NMI_LOCAL_APIC) { switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: @@ -697,17 +707,22 @@ void setup_apic_nmi_watchdog(void *unuse return; } } - __get_cpu_var(nmi_watchdog_ctlblk.enabled) = 1; + wd->enabled = 1; atomic_inc(&nmi_active); } void stop_apic_nmi_watchdog(void *unused) { + struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); + /* only support LOCAL and IO APICs for now */ if ((nmi_watchdog != NMI_LOCAL_APIC) && (nmi_watchdog != NMI_IO_APIC)) return; + if (wd->enabled == 0) + return; + if (nmi_watchdog == NMI_LOCAL_APIC) { switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: @@ -726,7 +741,7 @@ void stop_apic_nmi_watchdog(void *unused return; } } - __get_cpu_var(nmi_watchdog_ctlblk.enabled) = 0; + wd->enabled = 0; atomic_dec(&nmi_active); } _