Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 4149

kernel-2.6.18-194.11.1.el5.src.rpm

From: Aristeu Rozanski <aris@redhat.com>
Date: Wed, 20 Aug 2008 13:16:52 -0400
Subject: [x86_64] nmi: change nmi_active usage
Message-id: 20080820171647.960880000@redhat.com
O-Subject: [RHEL5.3 PATCH 06/25] nmi: change nmi_active usage
Bugzilla: 447618

https://bugzilla.redhat.com/show_bug.cgi?id=447618

add nmi_watchdog_active and use it to count the number of CPUs with the NMI
watchdog enabled. keep it in sync with nmi_active variable for kABI reasons.

upstream: f2802e7f571c05f9a901b1f5bd144aa730ccc88e

update: using a different name instead of making nmi_active atomic (kABI)

diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 8ddd38f..3f4aff5 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -53,6 +53,12 @@ static unsigned int lapic_nmi_owner;
 int nmi_active;		/* oprofile uses this */
 int panic_on_timeout;
 
+/*
+ * the upstream variable 'nmi_active' is called 'nmi_watchdog_active' on
+ * RHEL-5 for kABI reasons.
+ */
+atomic_t nmi_watchdog_active = ATOMIC_INIT(0);
+
 static DEFINE_PER_CPU(short, wd_enabled);
 
 unsigned int nmi_watchdog = NMI_DEFAULT;
@@ -166,6 +172,9 @@ int __init check_nmi_watchdog (void)
 	int *counts;
 	int cpu;
 
+	if (!atomic_read(&nmi_watchdog_active))
+		return 0;
+
 	counts = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
 	if (!counts)
 		return -1;
@@ -190,13 +199,20 @@ int __init check_nmi_watchdog (void)
 			       cpu,
 			       counts[cpu],
 			       cpu_pda(cpu)->__nmi_count);
-			nmi_active = 0;
+			if (atomic_dec_and_test(&nmi_watchdog_active))
+				nmi_active = 0;
 			lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG;
 			nmi_perfctr_msr = 0;
 			kfree(counts);
 			return -1;
 		}
 	}
+	if (!atomic_read(&nmi_watchdog_active)) {
+		atomic_set(&nmi_watchdog_active, -1);
+		nmi_active = -1;
+		return -1;
+	}
+
 	endflag = 1;
 	printk("OK.\n");
 
@@ -263,22 +279,27 @@ void release_lapic_nmi(void)
 		enable_lapic_nmi_watchdog();
 }
 
+static int old_ioapic_count;
 void disable_timer_nmi_watchdog(void)
 {
-	if ((nmi_watchdog != NMI_IO_APIC) || (nmi_active <= 0))
+	if ((nmi_watchdog != NMI_IO_APIC) ||
+	    (atomic_read(&nmi_watchdog_active) <= 0))
 		return;
 
 	disable_irq(0);
 	unset_nmi_callback();
+	old_ioapic_count = atomic_read(&nmi_watchdog_active);
+	atomic_set(&nmi_watchdog_active, -1);
 	nmi_active = -1;
 	nmi_watchdog = NMI_NONE;
 }
 
 void enable_timer_nmi_watchdog(void)
 {
-	if (nmi_active < 0) {
+	if (atomic_read(&nmi_watchdog_active) < 0) {
 		nmi_watchdog = NMI_IO_APIC;
 		touch_nmi_watchdog();
+		atomic_set(&nmi_watchdog_active, old_ioapic_count);
 		nmi_active = 1;
 		enable_irq(0);
 	}
@@ -317,7 +338,7 @@ static int __init init_lapic_nmi_sysfs(void)
 {
 	int error;
 
-	if (nmi_active == 0 || nmi_watchdog != NMI_LOCAL_APIC)
+	if (atomic_read(&nmi_watchdog_active) == 0 || nmi_watchdog != NMI_LOCAL_APIC)
 		return 0;
 
 	error = sysdev_class_register(&nmi_sysclass);
@@ -358,7 +379,8 @@ void setup_apic_nmi_watchdog(void)
 		/* FALL THROUGH */
 	case NMI_IO_APIC:
 		__get_cpu_var(wd_enabled) = 1;
-		atomic_inc(&nmi_active);
+		if (atomic_inc_return(&nmi_watchdog_active) == 1)
+			nmi_active = 1;
  	}
 }