aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/io_apic_64.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-03 13:28:46 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-03 13:28:46 -0400
commitf68ec0c24755e5cdb779be6240925f2175311d84 (patch)
treea7b7128e61a8456385d82bd1c7ca5f14eecbf2ca /arch/x86/kernel/io_apic_64.c
parent98920dc3d1113b883cbc73e3293446d3525c6042 (diff)
parent94aca1dac6f6d21f4b07e4864baf7768cabcc6e7 (diff)
Merge commit 'v2.6.27-rc8' into x86/setup
Diffstat (limited to 'arch/x86/kernel/io_apic_64.c')
-rw-r--r--arch/x86/kernel/io_apic_64.c78
1 files changed, 43 insertions, 35 deletions
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index 6510cde36b35..61a83b70c18f 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -45,6 +45,7 @@
45#include <asm/proto.h> 45#include <asm/proto.h>
46#include <asm/acpi.h> 46#include <asm/acpi.h>
47#include <asm/dma.h> 47#include <asm/dma.h>
48#include <asm/i8259.h>
48#include <asm/nmi.h> 49#include <asm/nmi.h>
49#include <asm/msidef.h> 50#include <asm/msidef.h>
50#include <asm/hypertransport.h> 51#include <asm/hypertransport.h>
@@ -100,7 +101,7 @@ int timer_through_8259 __initdata;
100static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; 101static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
101 102
102static DEFINE_SPINLOCK(ioapic_lock); 103static DEFINE_SPINLOCK(ioapic_lock);
103DEFINE_SPINLOCK(vector_lock); 104static DEFINE_SPINLOCK(vector_lock);
104 105
105/* 106/*
106 * # of IRQ routing registers 107 * # of IRQ routing registers
@@ -696,6 +697,19 @@ static int pin_2_irq(int idx, int apic, int pin)
696 return irq; 697 return irq;
697} 698}
698 699
700void lock_vector_lock(void)
701{
702 /* Used to the online set of cpus does not change
703 * during assign_irq_vector.
704 */
705 spin_lock(&vector_lock);
706}
707
708void unlock_vector_lock(void)
709{
710 spin_unlock(&vector_lock);
711}
712
699static int __assign_irq_vector(int irq, cpumask_t mask) 713static int __assign_irq_vector(int irq, cpumask_t mask)
700{ 714{
701 /* 715 /*
@@ -731,7 +745,7 @@ static int __assign_irq_vector(int irq, cpumask_t mask)
731 return 0; 745 return 0;
732 } 746 }
733 747
734 for_each_cpu_mask(cpu, mask) { 748 for_each_cpu_mask_nr(cpu, mask) {
735 cpumask_t domain, new_mask; 749 cpumask_t domain, new_mask;
736 int new_cpu; 750 int new_cpu;
737 int vector, offset; 751 int vector, offset;
@@ -752,7 +766,7 @@ next:
752 continue; 766 continue;
753 if (vector == IA32_SYSCALL_VECTOR) 767 if (vector == IA32_SYSCALL_VECTOR)
754 goto next; 768 goto next;
755 for_each_cpu_mask(new_cpu, new_mask) 769 for_each_cpu_mask_nr(new_cpu, new_mask)
756 if (per_cpu(vector_irq, new_cpu)[vector] != -1) 770 if (per_cpu(vector_irq, new_cpu)[vector] != -1)
757 goto next; 771 goto next;
758 /* Found one! */ 772 /* Found one! */
@@ -762,7 +776,7 @@ next:
762 cfg->move_in_progress = 1; 776 cfg->move_in_progress = 1;
763 cfg->old_domain = cfg->domain; 777 cfg->old_domain = cfg->domain;
764 } 778 }
765 for_each_cpu_mask(new_cpu, new_mask) 779 for_each_cpu_mask_nr(new_cpu, new_mask)
766 per_cpu(vector_irq, new_cpu)[vector] = irq; 780 per_cpu(vector_irq, new_cpu)[vector] = irq;
767 cfg->vector = vector; 781 cfg->vector = vector;
768 cfg->domain = domain; 782 cfg->domain = domain;
@@ -794,14 +808,14 @@ static void __clear_irq_vector(int irq)
794 808
795 vector = cfg->vector; 809 vector = cfg->vector;
796 cpus_and(mask, cfg->domain, cpu_online_map); 810 cpus_and(mask, cfg->domain, cpu_online_map);
797 for_each_cpu_mask(cpu, mask) 811 for_each_cpu_mask_nr(cpu, mask)
798 per_cpu(vector_irq, cpu)[vector] = -1; 812 per_cpu(vector_irq, cpu)[vector] = -1;
799 813
800 cfg->vector = 0; 814 cfg->vector = 0;
801 cpus_clear(cfg->domain); 815 cpus_clear(cfg->domain);
802} 816}
803 817
804static void __setup_vector_irq(int cpu) 818void __setup_vector_irq(int cpu)
805{ 819{
806 /* Initialize vector_irq on a new cpu */ 820 /* Initialize vector_irq on a new cpu */
807 /* This function must be called with vector_lock held */ 821 /* This function must be called with vector_lock held */
@@ -824,14 +838,6 @@ static void __setup_vector_irq(int cpu)
824 } 838 }
825} 839}
826 840
827void setup_vector_irq(int cpu)
828{
829 spin_lock(&vector_lock);
830 __setup_vector_irq(smp_processor_id());
831 spin_unlock(&vector_lock);
832}
833
834
835static struct irq_chip ioapic_chip; 841static struct irq_chip ioapic_chip;
836 842
837static void ioapic_register_intr(int irq, unsigned long trigger) 843static void ioapic_register_intr(int irq, unsigned long trigger)
@@ -1372,12 +1378,10 @@ static unsigned int startup_ioapic_irq(unsigned int irq)
1372static int ioapic_retrigger_irq(unsigned int irq) 1378static int ioapic_retrigger_irq(unsigned int irq)
1373{ 1379{
1374 struct irq_cfg *cfg = &irq_cfg[irq]; 1380 struct irq_cfg *cfg = &irq_cfg[irq];
1375 cpumask_t mask;
1376 unsigned long flags; 1381 unsigned long flags;
1377 1382
1378 spin_lock_irqsave(&vector_lock, flags); 1383 spin_lock_irqsave(&vector_lock, flags);
1379 mask = cpumask_of_cpu(first_cpu(cfg->domain)); 1384 send_IPI_mask(cpumask_of_cpu(first_cpu(cfg->domain)), cfg->vector);
1380 send_IPI_mask(mask, cfg->vector);
1381 spin_unlock_irqrestore(&vector_lock, flags); 1385 spin_unlock_irqrestore(&vector_lock, flags);
1382 1386
1383 return 1; 1387 return 1;
@@ -1696,8 +1700,9 @@ static inline void __init check_timer(void)
1696 pin2 = ioapic_i8259.pin; 1700 pin2 = ioapic_i8259.pin;
1697 apic2 = ioapic_i8259.apic; 1701 apic2 = ioapic_i8259.apic;
1698 1702
1699 apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", 1703 apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
1700 cfg->vector, apic1, pin1, apic2, pin2); 1704 "apic1=%d pin1=%d apic2=%d pin2=%d\n",
1705 cfg->vector, apic1, pin1, apic2, pin2);
1701 1706
1702 /* 1707 /*
1703 * Some BIOS writers are clueless and report the ExtINTA 1708 * Some BIOS writers are clueless and report the ExtINTA
@@ -1735,14 +1740,13 @@ static inline void __init check_timer(void)
1735 } 1740 }
1736 clear_IO_APIC_pin(apic1, pin1); 1741 clear_IO_APIC_pin(apic1, pin1);
1737 if (!no_pin1) 1742 if (!no_pin1)
1738 apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: " 1743 apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
1739 "8254 timer not connected to IO-APIC\n"); 1744 "8254 timer not connected to IO-APIC\n");
1740 1745
1741 apic_printk(APIC_VERBOSE,KERN_INFO 1746 apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
1742 "...trying to set up timer (IRQ0) " 1747 "(IRQ0) through the 8259A ...\n");
1743 "through the 8259A ... "); 1748 apic_printk(APIC_QUIET, KERN_INFO
1744 apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...", 1749 "..... (found apic %d pin %d) ...\n", apic2, pin2);
1745 apic2, pin2);
1746 /* 1750 /*
1747 * legacy devices should be connected to IO APIC #0 1751 * legacy devices should be connected to IO APIC #0
1748 */ 1752 */
@@ -1751,7 +1755,7 @@ static inline void __init check_timer(void)
1751 unmask_IO_APIC_irq(0); 1755 unmask_IO_APIC_irq(0);
1752 enable_8259A_irq(0); 1756 enable_8259A_irq(0);
1753 if (timer_irq_works()) { 1757 if (timer_irq_works()) {
1754 apic_printk(APIC_VERBOSE," works.\n"); 1758 apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
1755 timer_through_8259 = 1; 1759 timer_through_8259 = 1;
1756 if (nmi_watchdog == NMI_IO_APIC) { 1760 if (nmi_watchdog == NMI_IO_APIC) {
1757 disable_8259A_irq(0); 1761 disable_8259A_irq(0);
@@ -1765,29 +1769,32 @@ static inline void __init check_timer(void)
1765 */ 1769 */
1766 disable_8259A_irq(0); 1770 disable_8259A_irq(0);
1767 clear_IO_APIC_pin(apic2, pin2); 1771 clear_IO_APIC_pin(apic2, pin2);
1768 apic_printk(APIC_VERBOSE," failed.\n"); 1772 apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
1769 } 1773 }
1770 1774
1771 if (nmi_watchdog == NMI_IO_APIC) { 1775 if (nmi_watchdog == NMI_IO_APIC) {
1772 printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); 1776 apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
1777 "through the IO-APIC - disabling NMI Watchdog!\n");
1773 nmi_watchdog = NMI_NONE; 1778 nmi_watchdog = NMI_NONE;
1774 } 1779 }
1775 1780
1776 apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); 1781 apic_printk(APIC_QUIET, KERN_INFO
1782 "...trying to set up timer as Virtual Wire IRQ...\n");
1777 1783
1778 lapic_register_intr(0); 1784 lapic_register_intr(0);
1779 apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */ 1785 apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */
1780 enable_8259A_irq(0); 1786 enable_8259A_irq(0);
1781 1787
1782 if (timer_irq_works()) { 1788 if (timer_irq_works()) {
1783 apic_printk(APIC_VERBOSE," works.\n"); 1789 apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
1784 goto out; 1790 goto out;
1785 } 1791 }
1786 disable_8259A_irq(0); 1792 disable_8259A_irq(0);
1787 apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector); 1793 apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
1788 apic_printk(APIC_VERBOSE," failed.\n"); 1794 apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
1789 1795
1790 apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ..."); 1796 apic_printk(APIC_QUIET, KERN_INFO
1797 "...trying to set up timer as ExtINT IRQ...\n");
1791 1798
1792 init_8259A(0); 1799 init_8259A(0);
1793 make_8259A_irq(0); 1800 make_8259A_irq(0);
@@ -1796,11 +1803,12 @@ static inline void __init check_timer(void)
1796 unlock_ExtINT_logic(); 1803 unlock_ExtINT_logic();
1797 1804
1798 if (timer_irq_works()) { 1805 if (timer_irq_works()) {
1799 apic_printk(APIC_VERBOSE," works.\n"); 1806 apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
1800 goto out; 1807 goto out;
1801 } 1808 }
1802 apic_printk(APIC_VERBOSE," failed :(.\n"); 1809 apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
1803 panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n"); 1810 panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a "
1811 "report. Then try booting with the 'noapic' option.\n");
1804out: 1812out:
1805 local_irq_restore(flags); 1813 local_irq_restore(flags);
1806} 1814}