aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/io_apic.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai.lu@amd.com>2006-12-06 20:14:19 -0500
committerAndi Kleen <andi@basil.nowhere.org>2006-12-06 20:14:19 -0500
commitad892f5e0d01f3c3b475a688d1ddc211cf3ea56d (patch)
treedcbf5cf7cc237e5d3d85ab133525001423ffca42 /arch/x86_64/kernel/io_apic.c
parentf6ca8083c261864fc9de94ef99c3311ea259c5c3 (diff)
[PATCH] x86-64: check vector in setup_ioapic_dest to verify if need setup_IO_APIC_irq
setup_IO_APIC_irqs could fail to get vector for some device when you have too many devices, because at that time only boot cpu is online. So check vector for irq in setup_ioapic_dest and call setup_IO_APIC_irq to make sure IO-APIC irq-routing table is initialized. Also seperate setup_IO_APIC_irq from setup_IO_APIC_irqs. Signed-off-by: Yinghai Lu <yinghai.lu@amd.com> Signed-off-by: Andi Kleen <ak@suse.de> Cc: Andi Kleen <ak@suse.de> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@osdl.org>
Diffstat (limited to 'arch/x86_64/kernel/io_apic.c')
-rw-r--r--arch/x86_64/kernel/io_apic.c104
1 files changed, 61 insertions, 43 deletions
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index eaf0b708e67d..2a1dcd5f69c2 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -789,27 +789,65 @@ static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
789 handle_edge_irq, "edge"); 789 handle_edge_irq, "edge");
790 } 790 }
791} 791}
792 792static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
793static void __init setup_IO_APIC_irqs(void)
794{ 793{
795 struct IO_APIC_route_entry entry; 794 struct IO_APIC_route_entry entry;
796 int apic, pin, idx, irq, first_notcon = 1, vector; 795 int vector;
797 unsigned long flags; 796 unsigned long flags;
798 797
799 apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
800 798
801 for (apic = 0; apic < nr_ioapics; apic++) { 799 /*
802 for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { 800 * add it to the IO-APIC irq-routing table:
801 */
802 memset(&entry,0,sizeof(entry));
803 803
804 /* 804 entry.delivery_mode = INT_DELIVERY_MODE;
805 * add it to the IO-APIC irq-routing table: 805 entry.dest_mode = INT_DEST_MODE;
806 */ 806 entry.mask = 0; /* enable IRQ */
807 memset(&entry,0,sizeof(entry)); 807 entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
808
809 entry.trigger = irq_trigger(idx);
810 entry.polarity = irq_polarity(idx);
808 811
809 entry.delivery_mode = INT_DELIVERY_MODE; 812 if (irq_trigger(idx)) {
810 entry.dest_mode = INT_DEST_MODE; 813 entry.trigger = 1;
811 entry.mask = 0; /* enable IRQ */ 814 entry.mask = 1;
812 entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); 815 entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
816 }
817
818 if (!apic && !IO_APIC_IRQ(irq))
819 return;
820
821 if (IO_APIC_IRQ(irq)) {
822 cpumask_t mask;
823 vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
824 if (vector < 0)
825 return;
826
827 entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
828 entry.vector = vector;
829
830 ioapic_register_intr(irq, vector, IOAPIC_AUTO);
831 if (!apic && (irq < 16))
832 disable_8259A_irq(irq);
833 }
834
835 ioapic_write_entry(apic, pin, entry);
836
837 spin_lock_irqsave(&ioapic_lock, flags);
838 set_native_irq_info(irq, TARGET_CPUS);
839 spin_unlock_irqrestore(&ioapic_lock, flags);
840
841}
842
843static void __init setup_IO_APIC_irqs(void)
844{
845 int apic, pin, idx, irq, first_notcon = 1;
846
847 apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
848
849 for (apic = 0; apic < nr_ioapics; apic++) {
850 for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
813 851
814 idx = find_irq_entry(apic,pin,mp_INT); 852 idx = find_irq_entry(apic,pin,mp_INT);
815 if (idx == -1) { 853 if (idx == -1) {
@@ -821,39 +859,11 @@ static void __init setup_IO_APIC_irqs(void)
821 continue; 859 continue;
822 } 860 }
823 861
824 entry.trigger = irq_trigger(idx);
825 entry.polarity = irq_polarity(idx);
826
827 if (irq_trigger(idx)) {
828 entry.trigger = 1;
829 entry.mask = 1;
830 entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
831 }
832
833 irq = pin_2_irq(idx, apic, pin); 862 irq = pin_2_irq(idx, apic, pin);
834 add_pin_to_irq(irq, apic, pin); 863 add_pin_to_irq(irq, apic, pin);
835 864
836 if (!apic && !IO_APIC_IRQ(irq)) 865 setup_IO_APIC_irq(apic, pin, idx, irq);
837 continue;
838 866
839 if (IO_APIC_IRQ(irq)) {
840 cpumask_t mask;
841 vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
842 if (vector < 0)
843 continue;
844
845 entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
846 entry.vector = vector;
847
848 ioapic_register_intr(irq, vector, IOAPIC_AUTO);
849 if (!apic && (irq < 16))
850 disable_8259A_irq(irq);
851 }
852 ioapic_write_entry(apic, pin, entry);
853
854 spin_lock_irqsave(&ioapic_lock, flags);
855 set_native_irq_info(irq, TARGET_CPUS);
856 spin_unlock_irqrestore(&ioapic_lock, flags);
857 } 867 }
858 } 868 }
859 869
@@ -2139,7 +2149,15 @@ void __init setup_ioapic_dest(void)
2139 if (irq_entry == -1) 2149 if (irq_entry == -1)
2140 continue; 2150 continue;
2141 irq = pin_2_irq(irq_entry, ioapic, pin); 2151 irq = pin_2_irq(irq_entry, ioapic, pin);
2142 set_ioapic_affinity_irq(irq, TARGET_CPUS); 2152
2153 /* setup_IO_APIC_irqs could fail to get vector for some device
2154 * when you have too many devices, because at that time only boot
2155 * cpu is online.
2156 */
2157 if(!irq_vector[irq])
2158 setup_IO_APIC_irq(ioapic, pin, irq_entry, irq);
2159 else
2160 set_ioapic_affinity_irq(irq, TARGET_CPUS);
2143 } 2161 }
2144 2162
2145 } 2163 }