diff options
| -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 | } |
