diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/mpparse_32.c | 22 | ||||
-rw-r--r-- | arch/x86/kernel/mpparse_64.c | 70 |
2 files changed, 82 insertions, 10 deletions
diff --git a/arch/x86/kernel/mpparse_32.c b/arch/x86/kernel/mpparse_32.c index 1ad8a5d4e3ee..6376791cffe5 100644 --- a/arch/x86/kernel/mpparse_32.c +++ b/arch/x86/kernel/mpparse_32.c | |||
@@ -994,14 +994,15 @@ void __init mp_config_acpi_legacy_irqs(void) | |||
994 | } | 994 | } |
995 | } | 995 | } |
996 | 996 | ||
997 | #define MAX_GSI_NUM 4096 | ||
998 | #define IRQ_COMPRESSION_START 64 | ||
999 | |||
1000 | int mp_register_gsi(u32 gsi, int triggering, int polarity) | 997 | int mp_register_gsi(u32 gsi, int triggering, int polarity) |
1001 | { | 998 | { |
1002 | int ioapic = -1; | 999 | int ioapic = -1; |
1003 | int ioapic_pin = 0; | 1000 | int ioapic_pin = 0; |
1004 | int idx, bit = 0; | 1001 | int idx, bit = 0; |
1002 | #ifdef CONFIG_X86_32 | ||
1003 | #define MAX_GSI_NUM 4096 | ||
1004 | #define IRQ_COMPRESSION_START 64 | ||
1005 | |||
1005 | static int pci_irq = IRQ_COMPRESSION_START; | 1006 | static int pci_irq = IRQ_COMPRESSION_START; |
1006 | /* | 1007 | /* |
1007 | * Mapping between Global System Interrupts, which | 1008 | * Mapping between Global System Interrupts, which |
@@ -1009,6 +1010,11 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity) | |||
1009 | * assigned to actual devices. | 1010 | * assigned to actual devices. |
1010 | */ | 1011 | */ |
1011 | static int gsi_to_irq[MAX_GSI_NUM]; | 1012 | static int gsi_to_irq[MAX_GSI_NUM]; |
1013 | #else | ||
1014 | |||
1015 | if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) | ||
1016 | return gsi; | ||
1017 | #endif | ||
1012 | 1018 | ||
1013 | /* Don't set up the ACPI SCI because it's already set up */ | 1019 | /* Don't set up the ACPI SCI because it's already set up */ |
1014 | if (acpi_gbl_FADT.sci_interrupt == gsi) | 1020 | if (acpi_gbl_FADT.sci_interrupt == gsi) |
@@ -1022,8 +1028,10 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity) | |||
1022 | 1028 | ||
1023 | ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; | 1029 | ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; |
1024 | 1030 | ||
1031 | #ifdef CONFIG_X86_32 | ||
1025 | if (ioapic_renumber_irq) | 1032 | if (ioapic_renumber_irq) |
1026 | gsi = ioapic_renumber_irq(ioapic, gsi); | 1033 | gsi = ioapic_renumber_irq(ioapic, gsi); |
1034 | #endif | ||
1027 | 1035 | ||
1028 | /* | 1036 | /* |
1029 | * Avoid pin reprogramming. PRTs typically include entries | 1037 | * Avoid pin reprogramming. PRTs typically include entries |
@@ -1041,11 +1049,15 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity) | |||
1041 | if ((1 << bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) { | 1049 | if ((1 << bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) { |
1042 | Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", | 1050 | Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", |
1043 | mp_ioapic_routing[ioapic].apic_id, ioapic_pin); | 1051 | mp_ioapic_routing[ioapic].apic_id, ioapic_pin); |
1052 | #ifdef CONFIG_X86_32 | ||
1044 | return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]); | 1053 | return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]); |
1054 | #else | ||
1055 | return gsi; | ||
1056 | #endif | ||
1045 | } | 1057 | } |
1046 | 1058 | ||
1047 | mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1 << bit); | 1059 | mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1 << bit); |
1048 | 1060 | #ifdef CONFIG_X86_32 | |
1049 | /* | 1061 | /* |
1050 | * For GSI >= 64, use IRQ compression | 1062 | * For GSI >= 64, use IRQ compression |
1051 | */ | 1063 | */ |
@@ -1079,7 +1091,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity) | |||
1079 | return gsi; | 1091 | return gsi; |
1080 | } | 1092 | } |
1081 | } | 1093 | } |
1082 | 1094 | #endif | |
1083 | io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, | 1095 | io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, |
1084 | triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, | 1096 | triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, |
1085 | polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | 1097 | polarity == ACPI_ACTIVE_HIGH ? 0 : 1); |
diff --git a/arch/x86/kernel/mpparse_64.c b/arch/x86/kernel/mpparse_64.c index 8ad365136a6b..7d742577d68a 100644 --- a/arch/x86/kernel/mpparse_64.c +++ b/arch/x86/kernel/mpparse_64.c | |||
@@ -685,6 +685,8 @@ void __init find_smp_config(void) | |||
685 | 685 | ||
686 | #ifdef CONFIG_ACPI | 686 | #ifdef CONFIG_ACPI |
687 | 687 | ||
688 | #ifdef CONFIG_X86_IO_APIC | ||
689 | |||
688 | #define MP_ISA_BUS 0 | 690 | #define MP_ISA_BUS 0 |
689 | #define MP_MAX_IOAPIC_PIN 127 | 691 | #define MP_MAX_IOAPIC_PIN 127 |
690 | 692 | ||
@@ -770,7 +772,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) | |||
770 | int ioapic = -1; | 772 | int ioapic = -1; |
771 | int pin = -1; | 773 | int pin = -1; |
772 | 774 | ||
773 | /* | 775 | /* |
774 | * Convert 'gsi' to 'ioapic.pin'. | 776 | * Convert 'gsi' to 'ioapic.pin'. |
775 | */ | 777 | */ |
776 | ioapic = mp_find_ioapic(gsi); | 778 | ioapic = mp_find_ioapic(gsi); |
@@ -780,7 +782,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) | |||
780 | 782 | ||
781 | /* | 783 | /* |
782 | * TBD: This check is for faulty timer entries, where the override | 784 | * TBD: This check is for faulty timer entries, where the override |
783 | * erroneously sets the trigger to level, resulting in a HUGE | 785 | * erroneously sets the trigger to level, resulting in a HUGE |
784 | * increase of timer interrupts! | 786 | * increase of timer interrupts! |
785 | */ | 787 | */ |
786 | if ((bus_irq == 0) && (trigger == 3)) | 788 | if ((bus_irq == 0) && (trigger == 3)) |
@@ -886,9 +888,22 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity) | |||
886 | int ioapic = -1; | 888 | int ioapic = -1; |
887 | int ioapic_pin = 0; | 889 | int ioapic_pin = 0; |
888 | int idx, bit = 0; | 890 | int idx, bit = 0; |
891 | #ifdef CONFIG_X86_32 | ||
892 | #define MAX_GSI_NUM 4096 | ||
893 | #define IRQ_COMPRESSION_START 64 | ||
894 | |||
895 | static int pci_irq = IRQ_COMPRESSION_START; | ||
896 | /* | ||
897 | * Mapping between Global System Interrupts, which | ||
898 | * represent all possible interrupts, and IRQs | ||
899 | * assigned to actual devices. | ||
900 | */ | ||
901 | static int gsi_to_irq[MAX_GSI_NUM]; | ||
902 | #else | ||
889 | 903 | ||
890 | if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) | 904 | if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) |
891 | return gsi; | 905 | return gsi; |
906 | #endif | ||
892 | 907 | ||
893 | /* Don't set up the ACPI SCI because it's already set up */ | 908 | /* Don't set up the ACPI SCI because it's already set up */ |
894 | if (acpi_gbl_FADT.sci_interrupt == gsi) | 909 | if (acpi_gbl_FADT.sci_interrupt == gsi) |
@@ -902,8 +917,13 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity) | |||
902 | 917 | ||
903 | ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; | 918 | ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; |
904 | 919 | ||
905 | /* | 920 | #ifdef CONFIG_X86_32 |
906 | * Avoid pin reprogramming. PRTs typically include entries | 921 | if (ioapic_renumber_irq) |
922 | gsi = ioapic_renumber_irq(ioapic, gsi); | ||
923 | #endif | ||
924 | |||
925 | /* | ||
926 | * Avoid pin reprogramming. PRTs typically include entries | ||
907 | * with redundant pin->gsi mappings (but unique PCI devices); | 927 | * with redundant pin->gsi mappings (but unique PCI devices); |
908 | * we only program the IOAPIC on the first. | 928 | * we only program the IOAPIC on the first. |
909 | */ | 929 | */ |
@@ -918,14 +938,54 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity) | |||
918 | if ((1 << bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) { | 938 | if ((1 << bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) { |
919 | Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", | 939 | Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", |
920 | mp_ioapic_routing[ioapic].apic_id, ioapic_pin); | 940 | mp_ioapic_routing[ioapic].apic_id, ioapic_pin); |
941 | #ifdef CONFIG_X86_32 | ||
942 | return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]); | ||
943 | #else | ||
921 | return gsi; | 944 | return gsi; |
945 | #endif | ||
922 | } | 946 | } |
923 | 947 | ||
924 | mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1 << bit); | 948 | mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1 << bit); |
925 | 949 | #ifdef CONFIG_X86_32 | |
950 | /* | ||
951 | * For GSI >= 64, use IRQ compression | ||
952 | */ | ||
953 | if ((gsi >= IRQ_COMPRESSION_START) | ||
954 | && (triggering == ACPI_LEVEL_SENSITIVE)) { | ||
955 | /* | ||
956 | * For PCI devices assign IRQs in order, avoiding gaps | ||
957 | * due to unused I/O APIC pins. | ||
958 | */ | ||
959 | int irq = gsi; | ||
960 | if (gsi < MAX_GSI_NUM) { | ||
961 | /* | ||
962 | * Retain the VIA chipset work-around (gsi > 15), but | ||
963 | * avoid a problem where the 8254 timer (IRQ0) is setup | ||
964 | * via an override (so it's not on pin 0 of the ioapic), | ||
965 | * and at the same time, the pin 0 interrupt is a PCI | ||
966 | * type. The gsi > 15 test could cause these two pins | ||
967 | * to be shared as IRQ0, and they are not shareable. | ||
968 | * So test for this condition, and if necessary, avoid | ||
969 | * the pin collision. | ||
970 | */ | ||
971 | gsi = pci_irq++; | ||
972 | /* | ||
973 | * Don't assign IRQ used by ACPI SCI | ||
974 | */ | ||
975 | if (gsi == acpi_gbl_FADT.sci_interrupt) | ||
976 | gsi = pci_irq++; | ||
977 | gsi_to_irq[irq] = gsi; | ||
978 | } else { | ||
979 | printk(KERN_ERR "GSI %u is too high\n", gsi); | ||
980 | return gsi; | ||
981 | } | ||
982 | } | ||
983 | #endif | ||
926 | io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, | 984 | io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, |
927 | triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, | 985 | triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, |
928 | polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | 986 | polarity == ACPI_ACTIVE_HIGH ? 0 : 1); |
929 | return gsi; | 987 | return gsi; |
930 | } | 988 | } |
989 | |||
990 | #endif /* CONFIG_X86_IO_APIC */ | ||
931 | #endif /* CONFIG_ACPI */ | 991 | #endif /* CONFIG_ACPI */ |