diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-10-03 13:28:46 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-03 13:28:46 -0400 |
commit | f68ec0c24755e5cdb779be6240925f2175311d84 (patch) | |
tree | a7b7128e61a8456385d82bd1c7ca5f14eecbf2ca /arch/x86/kernel/io_apic_64.c | |
parent | 98920dc3d1113b883cbc73e3293446d3525c6042 (diff) | |
parent | 94aca1dac6f6d21f4b07e4864baf7768cabcc6e7 (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.c | 78 |
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; | |||
100 | static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; | 101 | static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; |
101 | 102 | ||
102 | static DEFINE_SPINLOCK(ioapic_lock); | 103 | static DEFINE_SPINLOCK(ioapic_lock); |
103 | DEFINE_SPINLOCK(vector_lock); | 104 | static 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 | ||
700 | void 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 | |||
708 | void unlock_vector_lock(void) | ||
709 | { | ||
710 | spin_unlock(&vector_lock); | ||
711 | } | ||
712 | |||
699 | static int __assign_irq_vector(int irq, cpumask_t mask) | 713 | static 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 | ||
804 | static void __setup_vector_irq(int cpu) | 818 | void __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 | ||
827 | void 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 | |||
835 | static struct irq_chip ioapic_chip; | 841 | static struct irq_chip ioapic_chip; |
836 | 842 | ||
837 | static void ioapic_register_intr(int irq, unsigned long trigger) | 843 | static void ioapic_register_intr(int irq, unsigned long trigger) |
@@ -1372,12 +1378,10 @@ static unsigned int startup_ioapic_irq(unsigned int irq) | |||
1372 | static int ioapic_retrigger_irq(unsigned int irq) | 1378 | static 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"); | ||
1804 | out: | 1812 | out: |
1805 | local_irq_restore(flags); | 1813 | local_irq_restore(flags); |
1806 | } | 1814 | } |