diff options
Diffstat (limited to 'arch/x86_64')
-rw-r--r-- | arch/x86_64/kernel/io_apic.c | 104 |
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 | 792 | static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq) | |
793 | static 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 | |||
843 | static 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 | } |