diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86_64/kernel/mpparse.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index ed6a5588146d..9c5aa2a790c7 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c | |||
@@ -906,11 +906,20 @@ void __init mp_config_acpi_legacy_irqs (void) | |||
906 | return; | 906 | return; |
907 | } | 907 | } |
908 | 908 | ||
909 | #define MAX_GSI_NUM 4096 | ||
910 | |||
909 | int mp_register_gsi(u32 gsi, int edge_level, int active_high_low) | 911 | int mp_register_gsi(u32 gsi, int edge_level, int active_high_low) |
910 | { | 912 | { |
911 | int ioapic = -1; | 913 | int ioapic = -1; |
912 | int ioapic_pin = 0; | 914 | int ioapic_pin = 0; |
913 | int idx, bit = 0; | 915 | int idx, bit = 0; |
916 | static int pci_irq = 16; | ||
917 | /* | ||
918 | * Mapping between Global System Interrupts, which | ||
919 | * represent all possible interrupts, to the IRQs | ||
920 | * assigned to actual devices. | ||
921 | */ | ||
922 | static int gsi_to_irq[MAX_GSI_NUM]; | ||
914 | 923 | ||
915 | if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) | 924 | if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) |
916 | return gsi; | 925 | return gsi; |
@@ -945,11 +954,21 @@ int mp_register_gsi(u32 gsi, int edge_level, int active_high_low) | |||
945 | if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) { | 954 | if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) { |
946 | Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", | 955 | Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", |
947 | mp_ioapic_routing[ioapic].apic_id, ioapic_pin); | 956 | mp_ioapic_routing[ioapic].apic_id, ioapic_pin); |
948 | return gsi; | 957 | return gsi_to_irq[gsi]; |
949 | } | 958 | } |
950 | 959 | ||
951 | mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit); | 960 | mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit); |
952 | 961 | ||
962 | if (edge_level) { | ||
963 | /* | ||
964 | * For PCI devices assign IRQs in order, avoiding gaps | ||
965 | * due to unused I/O APIC pins. | ||
966 | */ | ||
967 | int irq = gsi; | ||
968 | gsi = pci_irq++; | ||
969 | gsi_to_irq[irq] = gsi; | ||
970 | } | ||
971 | |||
953 | io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, | 972 | io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, |
954 | edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1, | 973 | edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1, |
955 | active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1); | 974 | active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1); |