Commit 660ab10c authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] 8259 timer ack fix

From: "Maciej W. Rozycki" <macro@ds2.pg.gda.pl>

Fix up the 8259 ack handling for buggy SMM firmware.

See http://www.ussg.iu.edu/hypermail/linux/kernel/0203.2/0956.html

Apparently the embedded 8259A-compatible core is not fully functional.
This patch lets the I/O APIC-driven NMI watchdog to function correctly.
Credit to Ross Dickson for discovering this.
parent d4634c58
...@@ -2150,6 +2150,10 @@ static inline void check_timer(void) ...@@ -2150,6 +2150,10 @@ static inline void check_timer(void)
{ {
int pin1, pin2; int pin1, pin2;
int vector; int vector;
unsigned int ver;
ver = apic_read(APIC_LVR);
ver = GET_APIC_VERSION(ver);
/* /*
* get/set the timer IRQ vector: * get/set the timer IRQ vector:
...@@ -2163,11 +2167,17 @@ static inline void check_timer(void) ...@@ -2163,11 +2167,17 @@ static inline void check_timer(void)
* mode for the 8259A whenever interrupts are routed * mode for the 8259A whenever interrupts are routed
* through I/O APICs. Also IRQ0 has to be enabled in * through I/O APICs. Also IRQ0 has to be enabled in
* the 8259A which implies the virtual wire has to be * the 8259A which implies the virtual wire has to be
* disabled in the local APIC. * disabled in the local APIC. Finally timer interrupts
* need to be acknowledged manually in the 8259A for
* do_slow_timeoffset() and for the i82489DX when using
* the NMI watchdog.
*/ */
apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
init_8259A(1); init_8259A(1);
timer_ack = 1; if (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver))
timer_ack = 1;
else
timer_ack = !cpu_has_tsc;
enable_8259A_irq(0); enable_8259A_irq(0);
pin1 = find_isa_irq_pin(0, mp_INT); pin1 = find_isa_irq_pin(0, mp_INT);
...@@ -2185,7 +2195,8 @@ static inline void check_timer(void) ...@@ -2185,7 +2195,8 @@ static inline void check_timer(void)
disable_8259A_irq(0); disable_8259A_irq(0);
setup_nmi(); setup_nmi();
enable_8259A_irq(0); enable_8259A_irq(0);
check_nmi_watchdog(); if (check_nmi_watchdog() < 0);
timer_ack = !cpu_has_tsc;
} }
return; return;
} }
...@@ -2208,7 +2219,8 @@ static inline void check_timer(void) ...@@ -2208,7 +2219,8 @@ static inline void check_timer(void)
add_pin_to_irq(0, 0, pin2); add_pin_to_irq(0, 0, pin2);
if (nmi_watchdog == NMI_IO_APIC) { if (nmi_watchdog == NMI_IO_APIC) {
setup_nmi(); setup_nmi();
check_nmi_watchdog(); if (check_nmi_watchdog() < 0);
timer_ack = !cpu_has_tsc;
} }
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment