Commit fea5f1e1 authored by Linus Torvalds's avatar Linus Torvalds

Revert "[PATCH] x86-64: Try multiple timer variants in check_timer"

This reverts commit b0268726, which has
been linked to several problem reports with IO-APIC and the timer.
Machines either don't boot because the timer doesn't happen, or we get
double timer interrupts because we end up double-routing the timer irq
through multiple interfaces.

See for example

	http://lkml.org/lkml/2006/12/16/101
	http://lkml.org/lkml/2007/1/3/9
	http://bugzilla.kernel.org/show_bug.cgi?id=7789

about some of the discussion.

Patches to fix this cleanup exist (and have been confirmed to work fine
at least for some of the affected cases) and we'll revisit it for
2.6.21, but this late in the -rc series we're better off just reverting
the incomplete commit that caused the problems.
Suggested-by: default avatarAdrian Bunk <bunk@stusta.de>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Yinghai Lu <yinghai.lu@amd.com>
Cc: Andrew Morton <akpm@osdl.org>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent bf81b464
...@@ -52,6 +52,10 @@ APICs ...@@ -52,6 +52,10 @@ APICs
apicmaintimer. Useful when your PIT timer is totally apicmaintimer. Useful when your PIT timer is totally
broken. broken.
disable_8254_timer / enable_8254_timer
Enable interrupt 0 timer routing over the 8254 in addition to over
the IO-APIC. The kernel tries to set a sensible default.
Early Console Early Console
syntax: earlyprintk=vga syntax: earlyprintk=vga
......
...@@ -69,6 +69,11 @@ static void nvidia_bugs(void) ...@@ -69,6 +69,11 @@ static void nvidia_bugs(void)
static void ati_bugs(void) static void ati_bugs(void)
{ {
if (timer_over_8254 == 1) {
timer_over_8254 = 0;
printk(KERN_INFO
"ATI board detected. Disabling timer routing over 8254.\n");
}
} }
static void intel_bugs(void) static void intel_bugs(void)
......
...@@ -55,6 +55,10 @@ int sis_apic_bug; /* not actually supported, dummy for compile */ ...@@ -55,6 +55,10 @@ int sis_apic_bug; /* not actually supported, dummy for compile */
static int no_timer_check; static int no_timer_check;
static int disable_timer_pin_1 __initdata;
int timer_over_8254 __initdata = 1;
/* Where if anywhere is the i8259 connect in external int mode */ /* Where if anywhere is the i8259 connect in external int mode */
static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
...@@ -350,6 +354,29 @@ static int __init disable_ioapic_setup(char *str) ...@@ -350,6 +354,29 @@ static int __init disable_ioapic_setup(char *str)
} }
early_param("noapic", disable_ioapic_setup); early_param("noapic", disable_ioapic_setup);
/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
static int __init disable_timer_pin_setup(char *arg)
{
disable_timer_pin_1 = 1;
return 1;
}
__setup("disable_timer_pin_1", disable_timer_pin_setup);
static int __init setup_disable_8254_timer(char *s)
{
timer_over_8254 = -1;
return 1;
}
static int __init setup_enable_8254_timer(char *s)
{
timer_over_8254 = 2;
return 1;
}
__setup("disable_8254_timer", setup_disable_8254_timer);
__setup("enable_8254_timer", setup_enable_8254_timer);
/* /*
* Find the IRQ entry number of a certain pin. * Find the IRQ entry number of a certain pin.
*/ */
...@@ -1568,33 +1595,10 @@ static inline void unlock_ExtINT_logic(void) ...@@ -1568,33 +1595,10 @@ static inline void unlock_ExtINT_logic(void)
* a wide range of boards and BIOS bugs. Fortunately only the timer IRQ * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ
* is so screwy. Thanks to Brian Perkins for testing/hacking this beast * is so screwy. Thanks to Brian Perkins for testing/hacking this beast
* fanatically on his truly buggy board. * fanatically on his truly buggy board.
*
* FIXME: really need to revamp this for modern platforms only.
*/ */
static inline void check_timer(void)
static int try_apic_pin(int apic, int pin, char *msg)
{
apic_printk(APIC_VERBOSE, KERN_INFO
"..TIMER: trying IO-APIC=%d PIN=%d %s",
apic, pin, msg);
/*
* Ok, does IRQ0 through the IOAPIC work?
*/
if (!no_timer_check && timer_irq_works()) {
nmi_watchdog_default();
if (nmi_watchdog == NMI_IO_APIC) {
disable_8259A_irq(0);
setup_nmi();
enable_8259A_irq(0);
}
return 1;
}
clear_IO_APIC_pin(apic, pin);
apic_printk(APIC_QUIET, KERN_ERR " .. failed\n");
return 0;
}
/* The function from hell */
static void check_timer(void)
{ {
int apic1, pin1, apic2, pin2; int apic1, pin1, apic2, pin2;
int vector; int vector;
...@@ -1615,43 +1619,61 @@ static void check_timer(void) ...@@ -1615,43 +1619,61 @@ static void check_timer(void)
*/ */
apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
init_8259A(1); init_8259A(1);
if (timer_over_8254 > 0)
enable_8259A_irq(0);
pin1 = find_isa_irq_pin(0, mp_INT); pin1 = find_isa_irq_pin(0, mp_INT);
apic1 = find_isa_irq_apic(0, mp_INT); apic1 = find_isa_irq_apic(0, mp_INT);
pin2 = ioapic_i8259.pin; pin2 = ioapic_i8259.pin;
apic2 = ioapic_i8259.apic; apic2 = ioapic_i8259.apic;
/* Do this first, otherwise we get double interrupts on ATI boards */ apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
if ((pin1 != -1) && try_apic_pin(apic1, pin1,"with 8259 IRQ0 disabled")) vector, apic1, pin1, apic2, pin2);
return;
/* Now try again with IRQ0 8259A enabled. if (pin1 != -1) {
Assumes timer is on IO-APIC 0 ?!? */ /*
enable_8259A_irq(0); * Ok, does IRQ0 through the IOAPIC work?
*/
unmask_IO_APIC_irq(0); unmask_IO_APIC_irq(0);
if (try_apic_pin(apic1, pin1, "with 8259 IRQ0 enabled")) if (!no_timer_check && timer_irq_works()) {
return; nmi_watchdog_default();
if (nmi_watchdog == NMI_IO_APIC) {
disable_8259A_irq(0); disable_8259A_irq(0);
setup_nmi();
/* Always try pin0 and pin2 on APIC 0 to handle buggy timer overrides enable_8259A_irq(0);
on Nvidia boards */ }
if (!(apic1 == 0 && pin1 == 0) && if (disable_timer_pin_1 > 0)
try_apic_pin(0, 0, "fallback with 8259 IRQ0 disabled")) clear_IO_APIC_pin(0, pin1);
return;
if (!(apic1 == 0 && pin1 == 2) &&
try_apic_pin(0, 2, "fallback with 8259 IRQ0 disabled"))
return; return;
}
clear_IO_APIC_pin(apic1, pin1);
apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not "
"connected to IO-APIC\n");
}
/* Then try pure 8259A routing on the 8259 as reported by BIOS*/ apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) "
enable_8259A_irq(0); "through the 8259A ... ");
if (pin2 != -1) { if (pin2 != -1) {
apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...",
apic2, pin2);
/*
* legacy devices should be connected to IO APIC #0
*/
setup_ExtINT_IRQ0_pin(apic2, pin2, vector); setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
if (try_apic_pin(apic2,pin2,"8259A broadcast ExtINT from BIOS")) if (timer_irq_works()) {
apic_printk(APIC_VERBOSE," works.\n");
nmi_watchdog_default();
if (nmi_watchdog == NMI_IO_APIC) {
setup_nmi();
}
return; return;
} }
/*
/* Tried all possibilities to go through the IO-APIC. Now come the * Cleanup, just in case ...
really cheesy fallbacks. */ */
clear_IO_APIC_pin(apic2, pin2);
}
apic_printk(APIC_VERBOSE," failed.\n");
if (nmi_watchdog == NMI_IO_APIC) { if (nmi_watchdog == NMI_IO_APIC) {
printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
......
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