aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/io_apic_32.c12
-rw-r--r--arch/x86/kernel/nmi_32.c9
2 files changed, 17 insertions, 4 deletions
diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c
index f35c6eb33da9..fc4bbc1d1331 100644
--- a/arch/x86/kernel/io_apic_32.c
+++ b/arch/x86/kernel/io_apic_32.c
@@ -2166,6 +2166,10 @@ static inline void __init check_timer(void)
2166{ 2166{
2167 int apic1, pin1, apic2, pin2; 2167 int apic1, pin1, apic2, pin2;
2168 int vector; 2168 int vector;
2169 unsigned int ver;
2170
2171 ver = apic_read(APIC_LVR);
2172 ver = GET_APIC_VERSION(ver);
2169 2173
2170 /* 2174 /*
2171 * get/set the timer IRQ vector: 2175 * get/set the timer IRQ vector:
@@ -2179,11 +2183,15 @@ static inline void __init check_timer(void)
2179 * mode for the 8259A whenever interrupts are routed 2183 * mode for the 8259A whenever interrupts are routed
2180 * through I/O APICs. Also IRQ0 has to be enabled in 2184 * through I/O APICs. Also IRQ0 has to be enabled in
2181 * the 8259A which implies the virtual wire has to be 2185 * the 8259A which implies the virtual wire has to be
2182 * disabled in the local APIC. 2186 * disabled in the local APIC. Finally timer interrupts
2187 * need to be acknowledged manually in the 8259A for
2188 * timer_interrupt() and for the i82489DX when using
2189 * the NMI watchdog.
2183 */ 2190 */
2184 apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); 2191 apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
2185 init_8259A(1); 2192 init_8259A(1);
2186 timer_ack = 1; 2193 timer_ack = !cpu_has_tsc;
2194 timer_ack |= (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
2187 if (timer_over_8254 > 0) 2195 if (timer_over_8254 > 0)
2188 enable_8259A_irq(0); 2196 enable_8259A_irq(0);
2189 2197
diff --git a/arch/x86/kernel/nmi_32.c b/arch/x86/kernel/nmi_32.c
index 600fd404e440..f5cc47c60b13 100644
--- a/arch/x86/kernel/nmi_32.c
+++ b/arch/x86/kernel/nmi_32.c
@@ -25,6 +25,7 @@
25 25
26#include <asm/smp.h> 26#include <asm/smp.h>
27#include <asm/nmi.h> 27#include <asm/nmi.h>
28#include <asm/timer.h>
28 29
29#include "mach_traps.h" 30#include "mach_traps.h"
30 31
@@ -83,7 +84,7 @@ static int __init check_nmi_watchdog(void)
83 84
84 prev_nmi_count = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL); 85 prev_nmi_count = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
85 if (!prev_nmi_count) 86 if (!prev_nmi_count)
86 return -1; 87 goto error;
87 88
88 printk(KERN_INFO "Testing NMI watchdog ... "); 89 printk(KERN_INFO "Testing NMI watchdog ... ");
89 90
@@ -117,7 +118,7 @@ static int __init check_nmi_watchdog(void)
117 if (!atomic_read(&nmi_active)) { 118 if (!atomic_read(&nmi_active)) {
118 kfree(prev_nmi_count); 119 kfree(prev_nmi_count);
119 atomic_set(&nmi_active, -1); 120 atomic_set(&nmi_active, -1);
120 return -1; 121 goto error;
121 } 122 }
122 printk("OK.\n"); 123 printk("OK.\n");
123 124
@@ -128,6 +129,10 @@ static int __init check_nmi_watchdog(void)
128 129
129 kfree(prev_nmi_count); 130 kfree(prev_nmi_count);
130 return 0; 131 return 0;
132error:
133 timer_ack = !cpu_has_tsc;
134
135 return -1;
131} 136}
132/* This needs to happen later in boot so counters are working */ 137/* This needs to happen later in boot so counters are working */
133late_initcall(check_nmi_watchdog); 138late_initcall(check_nmi_watchdog);