aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/io_apic_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/io_apic_64.c')
-rw-r--r--arch/x86/kernel/io_apic_64.c132
1 files changed, 80 insertions, 52 deletions
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index ef1a8dfcc529..e5ef60303562 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -61,7 +61,7 @@ struct irq_cfg {
61}; 61};
62 62
63/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ 63/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
64struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = { 64static struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = {
65 [0] = { .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, }, 65 [0] = { .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, },
66 [1] = { .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, }, 66 [1] = { .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, },
67 [2] = { .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, }, 67 [2] = { .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, },
@@ -90,7 +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_over_8254 __initdata = 1; 93int timer_through_8259 __initdata;
94 94
95/* Where if anywhere is the i8259 connect in external int mode */ 95/* Where if anywhere is the i8259 connect in external int mode */
96static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; 96static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
@@ -183,7 +183,7 @@ static bool io_apic_level_ack_pending(unsigned int irq)
183 break; 183 break;
184 reg = io_apic_read(entry->apic, 0x10 + pin*2); 184 reg = io_apic_read(entry->apic, 0x10 + pin*2);
185 /* Is the remote IRR bit set? */ 185 /* Is the remote IRR bit set? */
186 if ((reg >> 14) & 1) { 186 if (reg & IO_APIC_REDIR_REMOTE_IRR) {
187 spin_unlock_irqrestore(&ioapic_lock, flags); 187 spin_unlock_irqrestore(&ioapic_lock, flags);
188 return true; 188 return true;
189 } 189 }
@@ -298,7 +298,7 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
298 break; 298 break;
299 io_apic_write(apic, 0x11 + pin*2, dest); 299 io_apic_write(apic, 0x11 + pin*2, dest);
300 reg = io_apic_read(apic, 0x10 + pin*2); 300 reg = io_apic_read(apic, 0x10 + pin*2);
301 reg &= ~0x000000ff; 301 reg &= ~IO_APIC_REDIR_VECTOR_MASK;
302 reg |= vector; 302 reg |= vector;
303 io_apic_modify(apic, reg); 303 io_apic_modify(apic, reg);
304 if (!entry->next) 304 if (!entry->next)
@@ -360,16 +360,37 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin)
360 entry->pin = pin; 360 entry->pin = pin;
361} 361}
362 362
363/*
364 * Reroute an IRQ to a different pin.
365 */
366static void __init replace_pin_at_irq(unsigned int irq,
367 int oldapic, int oldpin,
368 int newapic, int newpin)
369{
370 struct irq_pin_list *entry = irq_2_pin + irq;
371
372 while (1) {
373 if (entry->apic == oldapic && entry->pin == oldpin) {
374 entry->apic = newapic;
375 entry->pin = newpin;
376 }
377 if (!entry->next)
378 break;
379 entry = irq_2_pin + entry->next;
380 }
381}
382
363 383
364#define DO_ACTION(name,R,ACTION, FINAL) \ 384#define DO_ACTION(name,R,ACTION, FINAL) \
365 \ 385 \
366 static void name##_IO_APIC_irq (unsigned int irq) \ 386 static void name##_IO_APIC_irq (unsigned int irq) \
367 __DO_ACTION(R, ACTION, FINAL) 387 __DO_ACTION(R, ACTION, FINAL)
368 388
369DO_ACTION( __mask, 0, |= 0x00010000, io_apic_sync(entry->apic) ) 389/* mask = 1 */
370 /* mask = 1 */ 390DO_ACTION(__mask, 0, |= IO_APIC_REDIR_MASKED, io_apic_sync(entry->apic))
371DO_ACTION( __unmask, 0, &= 0xfffeffff, ) 391
372 /* mask = 0 */ 392/* mask = 0 */
393DO_ACTION(__unmask, 0, &= ~IO_APIC_REDIR_MASKED, )
373 394
374static void mask_IO_APIC_irq (unsigned int irq) 395static void mask_IO_APIC_irq (unsigned int irq)
375{ 396{
@@ -430,20 +451,6 @@ static int __init disable_timer_pin_setup(char *arg)
430} 451}
431__setup("disable_timer_pin_1", disable_timer_pin_setup); 452__setup("disable_timer_pin_1", disable_timer_pin_setup);
432 453
433static int __init setup_disable_8254_timer(char *s)
434{
435 timer_over_8254 = -1;
436 return 1;
437}
438static int __init setup_enable_8254_timer(char *s)
439{
440 timer_over_8254 = 2;
441 return 1;
442}
443
444__setup("disable_8254_timer", setup_disable_8254_timer);
445__setup("enable_8254_timer", setup_enable_8254_timer);
446
447 454
448/* 455/*
449 * Find the IRQ entry number of a certain pin. 456 * Find the IRQ entry number of a certain pin.
@@ -911,26 +918,21 @@ static void __init setup_IO_APIC_irqs(void)
911} 918}
912 919
913/* 920/*
914 * Set up the 8259A-master output pin as broadcast to all 921 * Set up the timer pin, possibly with the 8259A-master behind.
915 * CPUs.
916 */ 922 */
917static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector) 923static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
924 int vector)
918{ 925{
919 struct IO_APIC_route_entry entry; 926 struct IO_APIC_route_entry entry;
920 927
921 memset(&entry, 0, sizeof(entry)); 928 memset(&entry, 0, sizeof(entry));
922 929
923 disable_8259A_irq(0);
924
925 /* mask LVT0 */
926 apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
927
928 /* 930 /*
929 * We use logical delivery to get the timer IRQ 931 * We use logical delivery to get the timer IRQ
930 * to the first CPU. 932 * to the first CPU.
931 */ 933 */
932 entry.dest_mode = INT_DEST_MODE; 934 entry.dest_mode = INT_DEST_MODE;
933 entry.mask = 0; /* unmask IRQ now */ 935 entry.mask = 1; /* mask IRQ now */
934 entry.dest = cpu_mask_to_apicid(TARGET_CPUS); 936 entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
935 entry.delivery_mode = INT_DELIVERY_MODE; 937 entry.delivery_mode = INT_DELIVERY_MODE;
936 entry.polarity = 0; 938 entry.polarity = 0;
@@ -939,7 +941,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
939 941
940 /* 942 /*
941 * The timer IRQ doesn't have to know that behind the 943 * The timer IRQ doesn't have to know that behind the
942 * scene we have a 8259A-master in AEOI mode ... 944 * scene we may have a 8259A-master in AEOI mode ...
943 */ 945 */
944 set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge"); 946 set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
945 947
@@ -947,8 +949,6 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
947 * Add it to the IO-APIC irq-routing table: 949 * Add it to the IO-APIC irq-routing table:
948 */ 950 */
949 ioapic_write_entry(apic, pin, entry); 951 ioapic_write_entry(apic, pin, entry);
950
951 enable_8259A_irq(0);
952} 952}
953 953
954void __apicdebuginit print_IO_APIC(void) 954void __apicdebuginit print_IO_APIC(void)
@@ -1077,6 +1077,7 @@ void __apicdebuginit print_local_APIC(void * dummy)
1077 1077
1078 printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", 1078 printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
1079 smp_processor_id(), hard_smp_processor_id()); 1079 smp_processor_id(), hard_smp_processor_id());
1080 v = apic_read(APIC_ID);
1080 printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, GET_APIC_ID(read_apic_id())); 1081 printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, GET_APIC_ID(read_apic_id()));
1081 v = apic_read(APIC_LVR); 1082 v = apic_read(APIC_LVR);
1082 printk(KERN_INFO "... APIC VERSION: %08x\n", v); 1083 printk(KERN_INFO "... APIC VERSION: %08x\n", v);
@@ -1659,6 +1660,7 @@ static inline void __init check_timer(void)
1659 struct irq_cfg *cfg = irq_cfg + 0; 1660 struct irq_cfg *cfg = irq_cfg + 0;
1660 int apic1, pin1, apic2, pin2; 1661 int apic1, pin1, apic2, pin2;
1661 unsigned long flags; 1662 unsigned long flags;
1663 int no_pin1 = 0;
1662 1664
1663 local_irq_save(flags); 1665 local_irq_save(flags);
1664 1666
@@ -1669,16 +1671,11 @@ static inline void __init check_timer(void)
1669 assign_irq_vector(0, TARGET_CPUS); 1671 assign_irq_vector(0, TARGET_CPUS);
1670 1672
1671 /* 1673 /*
1672 * Subtle, code in do_timer_interrupt() expects an AEOI 1674 * As IRQ0 is to be enabled in the 8259A, the virtual
1673 * mode for the 8259A whenever interrupts are routed 1675 * wire has to be disabled in the local APIC.
1674 * through I/O APICs. Also IRQ0 has to be enabled in
1675 * the 8259A which implies the virtual wire has to be
1676 * disabled in the local APIC.
1677 */ 1676 */
1678 apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); 1677 apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
1679 init_8259A(1); 1678 init_8259A(1);
1680 if (timer_over_8254 > 0)
1681 enable_8259A_irq(0);
1682 1679
1683 pin1 = find_isa_irq_pin(0, mp_INT); 1680 pin1 = find_isa_irq_pin(0, mp_INT);
1684 apic1 = find_isa_irq_apic(0, mp_INT); 1681 apic1 = find_isa_irq_apic(0, mp_INT);
@@ -1688,15 +1685,39 @@ static inline void __init check_timer(void)
1688 apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", 1685 apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
1689 cfg->vector, apic1, pin1, apic2, pin2); 1686 cfg->vector, apic1, pin1, apic2, pin2);
1690 1687
1688 /*
1689 * Some BIOS writers are clueless and report the ExtINTA
1690 * I/O APIC input from the cascaded 8259A as the timer
1691 * interrupt input. So just in case, if only one pin
1692 * was found above, try it both directly and through the
1693 * 8259A.
1694 */
1695 if (pin1 == -1) {
1696 pin1 = pin2;
1697 apic1 = apic2;
1698 no_pin1 = 1;
1699 } else if (pin2 == -1) {
1700 pin2 = pin1;
1701 apic2 = apic1;
1702 }
1703
1704 replace_pin_at_irq(0, 0, 0, apic1, pin1);
1705 apic1 = 0;
1706 pin1 = 0;
1707 setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
1708
1691 if (pin1 != -1) { 1709 if (pin1 != -1) {
1692 /* 1710 /*
1693 * Ok, does IRQ0 through the IOAPIC work? 1711 * Ok, does IRQ0 through the IOAPIC work?
1694 */ 1712 */
1713 if (no_pin1) {
1714 add_pin_to_irq(0, apic1, pin1);
1715 setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
1716 }
1695 unmask_IO_APIC_irq(0); 1717 unmask_IO_APIC_irq(0);
1696 if (!no_timer_check && timer_irq_works()) { 1718 if (!no_timer_check && timer_irq_works()) {
1697 nmi_watchdog_default(); 1719 nmi_watchdog_default();
1698 if (nmi_watchdog == NMI_IO_APIC) { 1720 if (nmi_watchdog == NMI_IO_APIC) {
1699 disable_8259A_irq(0);
1700 setup_nmi(); 1721 setup_nmi();
1701 enable_8259A_irq(0); 1722 enable_8259A_irq(0);
1702 } 1723 }
@@ -1705,42 +1726,48 @@ static inline void __init check_timer(void)
1705 goto out; 1726 goto out;
1706 } 1727 }
1707 clear_IO_APIC_pin(apic1, pin1); 1728 clear_IO_APIC_pin(apic1, pin1);
1708 apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not " 1729 if (!no_pin1)
1709 "connected to IO-APIC\n"); 1730 apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: "
1710 } 1731 "8254 timer not connected to IO-APIC\n");
1711 1732
1712 apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) " 1733 apic_printk(APIC_VERBOSE,KERN_INFO
1713 "through the 8259A ... "); 1734 "...trying to set up timer (IRQ0) "
1714 if (pin2 != -1) { 1735 "through the 8259A ... ");
1715 apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...", 1736 apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...",
1716 apic2, pin2); 1737 apic2, pin2);
1717 /* 1738 /*
1718 * legacy devices should be connected to IO APIC #0 1739 * legacy devices should be connected to IO APIC #0
1719 */ 1740 */
1720 setup_ExtINT_IRQ0_pin(apic2, pin2, cfg->vector); 1741 replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
1742 setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
1743 unmask_IO_APIC_irq(0);
1744 enable_8259A_irq(0);
1721 if (timer_irq_works()) { 1745 if (timer_irq_works()) {
1722 apic_printk(APIC_VERBOSE," works.\n"); 1746 apic_printk(APIC_VERBOSE," works.\n");
1747 timer_through_8259 = 1;
1723 nmi_watchdog_default(); 1748 nmi_watchdog_default();
1724 if (nmi_watchdog == NMI_IO_APIC) { 1749 if (nmi_watchdog == NMI_IO_APIC) {
1750 disable_8259A_irq(0);
1725 setup_nmi(); 1751 setup_nmi();
1752 enable_8259A_irq(0);
1726 } 1753 }
1727 goto out; 1754 goto out;
1728 } 1755 }
1729 /* 1756 /*
1730 * Cleanup, just in case ... 1757 * Cleanup, just in case ...
1731 */ 1758 */
1759 disable_8259A_irq(0);
1732 clear_IO_APIC_pin(apic2, pin2); 1760 clear_IO_APIC_pin(apic2, pin2);
1761 apic_printk(APIC_VERBOSE," failed.\n");
1733 } 1762 }
1734 apic_printk(APIC_VERBOSE," failed.\n");
1735 1763
1736 if (nmi_watchdog == NMI_IO_APIC) { 1764 if (nmi_watchdog == NMI_IO_APIC) {
1737 printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); 1765 printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
1738 nmi_watchdog = 0; 1766 nmi_watchdog = NMI_NONE;
1739 } 1767 }
1740 1768
1741 apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); 1769 apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
1742 1770
1743 disable_8259A_irq(0);
1744 irq_desc[0].chip = &lapic_irq_type; 1771 irq_desc[0].chip = &lapic_irq_type;
1745 apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */ 1772 apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */
1746 enable_8259A_irq(0); 1773 enable_8259A_irq(0);
@@ -1749,6 +1776,7 @@ static inline void __init check_timer(void)
1749 apic_printk(APIC_VERBOSE," works.\n"); 1776 apic_printk(APIC_VERBOSE," works.\n");
1750 goto out; 1777 goto out;
1751 } 1778 }
1779 disable_8259A_irq(0);
1752 apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector); 1780 apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
1753 apic_printk(APIC_VERBOSE," failed.\n"); 1781 apic_printk(APIC_VERBOSE," failed.\n");
1754 1782