aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2008-05-21 17:10:22 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-08 03:12:59 -0400
commit35542c5ebced864776d90d83d1e255016fd4c084 (patch)
tree2d190b468fbd76286762a25656452492b89acb9e /arch/x86/kernel
parenta1133d8e4ffc2db751eb987a2f3cf8ead67927c3 (diff)
x86: I/O APIC: clean up the 8259A on a NMI watchdog failure
There is no point in keeping the 8259A enabled if the I/O APIC NMI watchdog has failed and the 8259A is not used to pass through regular timer interrupts. This fixes problems with some systems where some logic gets confused. Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/io_apic_32.c2
-rw-r--r--arch/x86/kernel/io_apic_64.c2
-rw-r--r--arch/x86/kernel/nmi_32.c4
-rw-r--r--arch/x86/kernel/nmi_64.c11
4 files changed, 17 insertions, 2 deletions
diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c
index 41218ac75d1..7c7d88ebb96 100644
--- a/arch/x86/kernel/io_apic_32.c
+++ b/arch/x86/kernel/io_apic_32.c
@@ -58,6 +58,7 @@ static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
58static DEFINE_SPINLOCK(ioapic_lock); 58static DEFINE_SPINLOCK(ioapic_lock);
59static DEFINE_SPINLOCK(vector_lock); 59static DEFINE_SPINLOCK(vector_lock);
60 60
61int timer_through_8259 __initdata;
61 62
62/* 63/*
63 * Is the SiS APIC rmw bug present ? 64 * Is the SiS APIC rmw bug present ?
@@ -2194,6 +2195,7 @@ static inline void __init check_timer(void)
2194 enable_8259A_irq(0); 2195 enable_8259A_irq(0);
2195 if (timer_irq_works()) { 2196 if (timer_irq_works()) {
2196 printk("works.\n"); 2197 printk("works.\n");
2198 timer_through_8259 = 1;
2197 if (pin1 != -1) 2199 if (pin1 != -1)
2198 replace_pin_at_irq(0, apic1, pin1, apic2, pin2); 2200 replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
2199 else 2201 else
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index aa45a85c4d1..2a60bfb7446 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -90,6 +90,7 @@ static int no_timer_check;
90 90
91static int disable_timer_pin_1 __initdata; 91static int disable_timer_pin_1 __initdata;
92 92
93int timer_through_8259 __initdata;
93 94
94/* Where if anywhere is the i8259 connect in external int mode */ 95/* Where if anywhere is the i8259 connect in external int mode */
95static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; 96static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
@@ -1700,6 +1701,7 @@ static inline void __init check_timer(void)
1700 enable_8259A_irq(0); 1701 enable_8259A_irq(0);
1701 if (timer_irq_works()) { 1702 if (timer_irq_works()) {
1702 apic_printk(APIC_VERBOSE," works.\n"); 1703 apic_printk(APIC_VERBOSE," works.\n");
1704 timer_through_8259 = 1;
1703 nmi_watchdog_default(); 1705 nmi_watchdog_default();
1704 if (nmi_watchdog == NMI_IO_APIC) { 1706 if (nmi_watchdog == NMI_IO_APIC) {
1705 disable_8259A_irq(0); 1707 disable_8259A_irq(0);
diff --git a/arch/x86/kernel/nmi_32.c b/arch/x86/kernel/nmi_32.c
index d322901c38e..6580dae4627 100644
--- a/arch/x86/kernel/nmi_32.c
+++ b/arch/x86/kernel/nmi_32.c
@@ -24,6 +24,8 @@
24#include <linux/kdebug.h> 24#include <linux/kdebug.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26 26
27#include <asm/i8259.h>
28#include <asm/io_apic.h>
27#include <asm/smp.h> 29#include <asm/smp.h>
28#include <asm/nmi.h> 30#include <asm/nmi.h>
29#include <asm/timer.h> 31#include <asm/timer.h>
@@ -131,6 +133,8 @@ int __init check_nmi_watchdog(void)
131 kfree(prev_nmi_count); 133 kfree(prev_nmi_count);
132 return 0; 134 return 0;
133error: 135error:
136 if (nmi_watchdog == NMI_IO_APIC && !timer_through_8259)
137 disable_8259A_irq(0);
134 timer_ack = 0; 138 timer_ack = 0;
135 139
136 return -1; 140 return -1;
diff --git a/arch/x86/kernel/nmi_64.c b/arch/x86/kernel/nmi_64.c
index 5a29ded994f..0060e44e898 100644
--- a/arch/x86/kernel/nmi_64.c
+++ b/arch/x86/kernel/nmi_64.c
@@ -21,6 +21,8 @@
21#include <linux/cpumask.h> 21#include <linux/cpumask.h>
22#include <linux/kdebug.h> 22#include <linux/kdebug.h>
23 23
24#include <asm/i8259.h>
25#include <asm/io_apic.h>
24#include <asm/smp.h> 26#include <asm/smp.h>
25#include <asm/nmi.h> 27#include <asm/nmi.h>
26#include <asm/proto.h> 28#include <asm/proto.h>
@@ -90,7 +92,7 @@ int __init check_nmi_watchdog(void)
90 92
91 prev_nmi_count = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL); 93 prev_nmi_count = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
92 if (!prev_nmi_count) 94 if (!prev_nmi_count)
93 return -1; 95 goto error;
94 96
95 printk(KERN_INFO "Testing NMI watchdog ... "); 97 printk(KERN_INFO "Testing NMI watchdog ... ");
96 98
@@ -121,7 +123,7 @@ int __init check_nmi_watchdog(void)
121 if (!atomic_read(&nmi_active)) { 123 if (!atomic_read(&nmi_active)) {
122 kfree(prev_nmi_count); 124 kfree(prev_nmi_count);
123 atomic_set(&nmi_active, -1); 125 atomic_set(&nmi_active, -1);
124 return -1; 126 goto error;
125 } 127 }
126 printk("OK.\n"); 128 printk("OK.\n");
127 129
@@ -132,6 +134,11 @@ int __init check_nmi_watchdog(void)
132 134
133 kfree(prev_nmi_count); 135 kfree(prev_nmi_count);
134 return 0; 136 return 0;
137error:
138 if (nmi_watchdog == NMI_IO_APIC && !timer_through_8259)
139 disable_8259A_irq(0);
140
141 return -1;
135} 142}
136 143
137static int __init setup_nmi_watchdog(char *str) 144static int __init setup_nmi_watchdog(char *str)