aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/io_apic.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.osdl.org>2007-01-08 18:04:46 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2007-01-08 18:04:46 -0500
commitfea5f1e19611d94fbf3905875a427c4cb959cd06 (patch)
tree5a4c0584eea3ba74745e836e370fa1bbd0dacb02 /arch/x86_64/kernel/io_apic.c
parentbf81b46482c0fa8ea638e409d39768ea92a6b0f0 (diff)
Revert "[PATCH] x86-64: Try multiple timer variants in check_timer"
This reverts commit b026872601976f666bae77b609dc490d1834bf77, 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: Adrian 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: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64/kernel/io_apic.c')
-rw-r--r--arch/x86_64/kernel/io_apic.c124
1 files changed, 73 insertions, 51 deletions
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 2a1dcd5f69c2..d7bad90a5ad8 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -55,6 +55,10 @@ int sis_apic_bug; /* not actually supported, dummy for compile */
55 55
56static int no_timer_check; 56static int no_timer_check;
57 57
58static int disable_timer_pin_1 __initdata;
59
60int timer_over_8254 __initdata = 1;
61
58/* Where if anywhere is the i8259 connect in external int mode */ 62/* Where if anywhere is the i8259 connect in external int mode */
59static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; 63static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
60 64
@@ -350,6 +354,29 @@ static int __init disable_ioapic_setup(char *str)
350} 354}
351early_param("noapic", disable_ioapic_setup); 355early_param("noapic", disable_ioapic_setup);
352 356
357/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
358static int __init disable_timer_pin_setup(char *arg)
359{
360 disable_timer_pin_1 = 1;
361 return 1;
362}
363__setup("disable_timer_pin_1", disable_timer_pin_setup);
364
365static int __init setup_disable_8254_timer(char *s)
366{
367 timer_over_8254 = -1;
368 return 1;
369}
370static int __init setup_enable_8254_timer(char *s)
371{
372 timer_over_8254 = 2;
373 return 1;
374}
375
376__setup("disable_8254_timer", setup_disable_8254_timer);
377__setup("enable_8254_timer", setup_enable_8254_timer);
378
379
353/* 380/*
354 * Find the IRQ entry number of a certain pin. 381 * Find the IRQ entry number of a certain pin.
355 */ 382 */
@@ -1568,33 +1595,10 @@ static inline void unlock_ExtINT_logic(void)
1568 * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ 1595 * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ
1569 * is so screwy. Thanks to Brian Perkins for testing/hacking this beast 1596 * is so screwy. Thanks to Brian Perkins for testing/hacking this beast
1570 * fanatically on his truly buggy board. 1597 * fanatically on his truly buggy board.
1598 *
1599 * FIXME: really need to revamp this for modern platforms only.
1571 */ 1600 */
1572 1601static inline void check_timer(void)
1573static int try_apic_pin(int apic, int pin, char *msg)
1574{
1575 apic_printk(APIC_VERBOSE, KERN_INFO
1576 "..TIMER: trying IO-APIC=%d PIN=%d %s",
1577 apic, pin, msg);
1578
1579 /*
1580 * Ok, does IRQ0 through the IOAPIC work?
1581 */
1582 if (!no_timer_check && timer_irq_works()) {
1583 nmi_watchdog_default();
1584 if (nmi_watchdog == NMI_IO_APIC) {
1585 disable_8259A_irq(0);
1586 setup_nmi();
1587 enable_8259A_irq(0);
1588 }
1589 return 1;
1590 }
1591 clear_IO_APIC_pin(apic, pin);
1592 apic_printk(APIC_QUIET, KERN_ERR " .. failed\n");
1593 return 0;
1594}
1595
1596/* The function from hell */
1597static void check_timer(void)
1598{ 1602{
1599 int apic1, pin1, apic2, pin2; 1603 int apic1, pin1, apic2, pin2;
1600 int vector; 1604 int vector;
@@ -1615,43 +1619,61 @@ static void check_timer(void)
1615 */ 1619 */
1616 apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); 1620 apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
1617 init_8259A(1); 1621 init_8259A(1);
1622 if (timer_over_8254 > 0)
1623 enable_8259A_irq(0);
1618 1624
1619 pin1 = find_isa_irq_pin(0, mp_INT); 1625 pin1 = find_isa_irq_pin(0, mp_INT);
1620 apic1 = find_isa_irq_apic(0, mp_INT); 1626 apic1 = find_isa_irq_apic(0, mp_INT);
1621 pin2 = ioapic_i8259.pin; 1627 pin2 = ioapic_i8259.pin;
1622 apic2 = ioapic_i8259.apic; 1628 apic2 = ioapic_i8259.apic;
1623 1629
1624 /* Do this first, otherwise we get double interrupts on ATI boards */ 1630 apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
1625 if ((pin1 != -1) && try_apic_pin(apic1, pin1,"with 8259 IRQ0 disabled")) 1631 vector, apic1, pin1, apic2, pin2);
1626 return;
1627 1632
1628 /* Now try again with IRQ0 8259A enabled. 1633 if (pin1 != -1) {
1629 Assumes timer is on IO-APIC 0 ?!? */ 1634 /*
1630 enable_8259A_irq(0); 1635 * Ok, does IRQ0 through the IOAPIC work?
1631 unmask_IO_APIC_irq(0); 1636 */
1632 if (try_apic_pin(apic1, pin1, "with 8259 IRQ0 enabled")) 1637 unmask_IO_APIC_irq(0);
1633 return; 1638 if (!no_timer_check && timer_irq_works()) {
1634 disable_8259A_irq(0); 1639 nmi_watchdog_default();
1635 1640 if (nmi_watchdog == NMI_IO_APIC) {
1636 /* Always try pin0 and pin2 on APIC 0 to handle buggy timer overrides 1641 disable_8259A_irq(0);
1637 on Nvidia boards */ 1642 setup_nmi();
1638 if (!(apic1 == 0 && pin1 == 0) && 1643 enable_8259A_irq(0);
1639 try_apic_pin(0, 0, "fallback with 8259 IRQ0 disabled")) 1644 }
1640 return; 1645 if (disable_timer_pin_1 > 0)
1641 if (!(apic1 == 0 && pin1 == 2) && 1646 clear_IO_APIC_pin(0, pin1);
1642 try_apic_pin(0, 2, "fallback with 8259 IRQ0 disabled")) 1647 return;
1643 return; 1648 }
1649 clear_IO_APIC_pin(apic1, pin1);
1650 apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not "
1651 "connected to IO-APIC\n");
1652 }
1644 1653
1645 /* Then try pure 8259A routing on the 8259 as reported by BIOS*/ 1654 apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) "
1646 enable_8259A_irq(0); 1655 "through the 8259A ... ");
1647 if (pin2 != -1) { 1656 if (pin2 != -1) {
1657 apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...",
1658 apic2, pin2);
1659 /*
1660 * legacy devices should be connected to IO APIC #0
1661 */
1648 setup_ExtINT_IRQ0_pin(apic2, pin2, vector); 1662 setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
1649 if (try_apic_pin(apic2,pin2,"8259A broadcast ExtINT from BIOS")) 1663 if (timer_irq_works()) {
1664 apic_printk(APIC_VERBOSE," works.\n");
1665 nmi_watchdog_default();
1666 if (nmi_watchdog == NMI_IO_APIC) {
1667 setup_nmi();
1668 }
1650 return; 1669 return;
1670 }
1671 /*
1672 * Cleanup, just in case ...
1673 */
1674 clear_IO_APIC_pin(apic2, pin2);
1651 } 1675 }
1652 1676 apic_printk(APIC_VERBOSE," failed.\n");
1653 /* Tried all possibilities to go through the IO-APIC. Now come the
1654 really cheesy fallbacks. */
1655 1677
1656 if (nmi_watchdog == NMI_IO_APIC) { 1678 if (nmi_watchdog == NMI_IO_APIC) {
1657 printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); 1679 printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");