diff options
author | Alexey Starikovskiy <astarikovskiy@suse.de> | 2008-05-14 11:02:57 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-25 04:55:12 -0400 |
commit | 11113f84c72bd832dc4e76122e613b0e623e2346 (patch) | |
tree | a2c8f05d35cb41f6b14eae3908278af08902a31b /arch/x86/kernel/acpi/boot.c | |
parent | 32c5061265caf201d6a2c0d02181e2b68769c22c (diff) |
x86: complete move ACPI from mpparse.c
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/acpi/boot.c')
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 6f20fa92bbaf..b2ad09c4c6ae 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -846,6 +846,310 @@ static int __init acpi_parse_madt_lapic_entries(void) | |||
846 | #endif /* CONFIG_X86_LOCAL_APIC */ | 846 | #endif /* CONFIG_X86_LOCAL_APIC */ |
847 | 847 | ||
848 | #ifdef CONFIG_X86_IO_APIC | 848 | #ifdef CONFIG_X86_IO_APIC |
849 | #define MP_ISA_BUS 0 | ||
850 | |||
851 | #if defined(CONFIG_X86_ES7000) || defined(CONFIG_X86_GENERICARCH) | ||
852 | extern int es7000_plat; | ||
853 | #endif | ||
854 | |||
855 | static struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS]; | ||
856 | |||
857 | static int mp_find_ioapic(int gsi) | ||
858 | { | ||
859 | int i = 0; | ||
860 | |||
861 | /* Find the IOAPIC that manages this GSI. */ | ||
862 | for (i = 0; i < nr_ioapics; i++) { | ||
863 | if ((gsi >= mp_ioapic_routing[i].gsi_base) | ||
864 | && (gsi <= mp_ioapic_routing[i].gsi_end)) | ||
865 | return i; | ||
866 | } | ||
867 | |||
868 | printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); | ||
869 | return -1; | ||
870 | } | ||
871 | |||
872 | static u8 __init uniq_ioapic_id(u8 id) | ||
873 | { | ||
874 | #ifdef CONFIG_X86_32 | ||
875 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && | ||
876 | !APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) | ||
877 | return io_apic_get_unique_id(nr_ioapics, id); | ||
878 | else | ||
879 | return id; | ||
880 | #else | ||
881 | int i; | ||
882 | DECLARE_BITMAP(used, 256); | ||
883 | bitmap_zero(used, 256); | ||
884 | for (i = 0; i < nr_ioapics; i++) { | ||
885 | struct mpc_config_ioapic *ia = &mp_ioapics[i]; | ||
886 | __set_bit(ia->mpc_apicid, used); | ||
887 | } | ||
888 | if (!test_bit(id, used)) | ||
889 | return id; | ||
890 | return find_first_zero_bit(used, 256); | ||
891 | #endif | ||
892 | } | ||
893 | |||
894 | static int bad_ioapic(unsigned long address) | ||
895 | { | ||
896 | if (nr_ioapics >= MAX_IO_APICS) { | ||
897 | printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " | ||
898 | "(found %d)\n", MAX_IO_APICS, nr_ioapics); | ||
899 | panic("Recompile kernel with bigger MAX_IO_APICS!\n"); | ||
900 | } | ||
901 | if (!address) { | ||
902 | printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address" | ||
903 | " found in table, skipping!\n"); | ||
904 | return 1; | ||
905 | } | ||
906 | return 0; | ||
907 | } | ||
908 | |||
909 | void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) | ||
910 | { | ||
911 | int idx = 0; | ||
912 | |||
913 | if (bad_ioapic(address)) | ||
914 | return; | ||
915 | |||
916 | idx = nr_ioapics; | ||
917 | |||
918 | mp_ioapics[idx].mpc_type = MP_IOAPIC; | ||
919 | mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE; | ||
920 | mp_ioapics[idx].mpc_apicaddr = address; | ||
921 | |||
922 | set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); | ||
923 | mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id); | ||
924 | #ifdef CONFIG_X86_32 | ||
925 | mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); | ||
926 | #else | ||
927 | mp_ioapics[idx].mpc_apicver = 0; | ||
928 | #endif | ||
929 | /* | ||
930 | * Build basic GSI lookup table to facilitate gsi->io_apic lookups | ||
931 | * and to prevent reprogramming of IOAPIC pins (PCI GSIs). | ||
932 | */ | ||
933 | mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid; | ||
934 | mp_ioapic_routing[idx].gsi_base = gsi_base; | ||
935 | mp_ioapic_routing[idx].gsi_end = gsi_base + | ||
936 | io_apic_get_redir_entries(idx); | ||
937 | |||
938 | printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " | ||
939 | "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, | ||
940 | mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, | ||
941 | mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end); | ||
942 | |||
943 | nr_ioapics++; | ||
944 | } | ||
945 | |||
946 | void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) | ||
947 | { | ||
948 | int ioapic = -1; | ||
949 | int pin = -1; | ||
950 | |||
951 | /* | ||
952 | * Convert 'gsi' to 'ioapic.pin'. | ||
953 | */ | ||
954 | ioapic = mp_find_ioapic(gsi); | ||
955 | if (ioapic < 0) | ||
956 | return; | ||
957 | pin = gsi - mp_ioapic_routing[ioapic].gsi_base; | ||
958 | |||
959 | /* | ||
960 | * TBD: This check is for faulty timer entries, where the override | ||
961 | * erroneously sets the trigger to level, resulting in a HUGE | ||
962 | * increase of timer interrupts! | ||
963 | */ | ||
964 | if ((bus_irq == 0) && (trigger == 3)) | ||
965 | trigger = 1; | ||
966 | |||
967 | mp_irqs[mp_irq_entries].mpc_type = MP_INTSRC; | ||
968 | mp_irqs[mp_irq_entries].mpc_irqtype = mp_INT; | ||
969 | mp_irqs[mp_irq_entries].mpc_irqflag = (trigger << 2) | polarity; | ||
970 | mp_irqs[mp_irq_entries].mpc_srcbus = MP_ISA_BUS; | ||
971 | mp_irqs[mp_irq_entries].mpc_srcbusirq = bus_irq; /* IRQ */ | ||
972 | mp_irqs[mp_irq_entries].mpc_dstapic = | ||
973 | mp_ioapics[ioapic].mpc_apicid; /* APIC ID */ | ||
974 | mp_irqs[mp_irq_entries].mpc_dstirq = pin; /* INTIN# */ | ||
975 | |||
976 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | ||
977 | panic("Max # of irq sources exceeded!!\n"); | ||
978 | |||
979 | } | ||
980 | |||
981 | void __init mp_config_acpi_legacy_irqs(void) | ||
982 | { | ||
983 | int i = 0; | ||
984 | int ioapic = -1; | ||
985 | |||
986 | #if defined (CONFIG_MCA) || defined (CONFIG_EISA) | ||
987 | /* | ||
988 | * Fabricate the legacy ISA bus (bus #31). | ||
989 | */ | ||
990 | mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; | ||
991 | #endif | ||
992 | set_bit(MP_ISA_BUS, mp_bus_not_pci); | ||
993 | Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); | ||
994 | |||
995 | #if defined(CONFIG_X86_ES7000) || defined(CONFIG_X86_GENERICARCH) | ||
996 | /* | ||
997 | * Older generations of ES7000 have no legacy identity mappings | ||
998 | */ | ||
999 | if (es7000_plat == 1) | ||
1000 | return; | ||
1001 | #endif | ||
1002 | |||
1003 | /* | ||
1004 | * Locate the IOAPIC that manages the ISA IRQs (0-15). | ||
1005 | */ | ||
1006 | ioapic = mp_find_ioapic(0); | ||
1007 | if (ioapic < 0) | ||
1008 | return; | ||
1009 | |||
1010 | mp_irqs[mp_irq_entries].mpc_type = MP_INTSRC; | ||
1011 | mp_irqs[mp_irq_entries].mpc_irqflag = 0; /* Conforming */ | ||
1012 | mp_irqs[mp_irq_entries].mpc_srcbus = MP_ISA_BUS; | ||
1013 | #ifdef CONFIG_X86_IO_APIC | ||
1014 | mp_irqs[mp_irq_entries].mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; | ||
1015 | #endif | ||
1016 | /* | ||
1017 | * Use the default configuration for the IRQs 0-15. Unless | ||
1018 | * overridden by (MADT) interrupt source override entries. | ||
1019 | */ | ||
1020 | for (i = 0; i < 16; i++) { | ||
1021 | int idx; | ||
1022 | |||
1023 | for (idx = 0; idx < mp_irq_entries; idx++) { | ||
1024 | struct mpc_config_intsrc *irq = mp_irqs + idx; | ||
1025 | |||
1026 | /* Do we already have a mapping for this ISA IRQ? */ | ||
1027 | if (irq->mpc_srcbus == MP_ISA_BUS | ||
1028 | && irq->mpc_srcbusirq == i) | ||
1029 | break; | ||
1030 | |||
1031 | /* Do we already have a mapping for this IOAPIC pin */ | ||
1032 | if ((irq->mpc_dstapic == | ||
1033 | mp_irqs[mp_irq_entries].mpc_dstapic) && | ||
1034 | (irq->mpc_dstirq == i)) | ||
1035 | break; | ||
1036 | } | ||
1037 | |||
1038 | if (idx != mp_irq_entries) { | ||
1039 | printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i); | ||
1040 | continue; /* IRQ already used */ | ||
1041 | } | ||
1042 | |||
1043 | mp_irqs[mp_irq_entries].mpc_irqtype = mp_INT; | ||
1044 | mp_irqs[mp_irq_entries].mpc_srcbusirq = i; /* Identity mapped */ | ||
1045 | mp_irqs[mp_irq_entries].mpc_dstirq = i; | ||
1046 | |||
1047 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | ||
1048 | panic("Max # of irq sources exceeded!!\n"); | ||
1049 | } | ||
1050 | } | ||
1051 | |||
1052 | int mp_register_gsi(u32 gsi, int triggering, int polarity) | ||
1053 | { | ||
1054 | int ioapic; | ||
1055 | int ioapic_pin; | ||
1056 | #ifdef CONFIG_X86_32 | ||
1057 | #define MAX_GSI_NUM 4096 | ||
1058 | #define IRQ_COMPRESSION_START 64 | ||
1059 | |||
1060 | static int pci_irq = IRQ_COMPRESSION_START; | ||
1061 | /* | ||
1062 | * Mapping between Global System Interrupts, which | ||
1063 | * represent all possible interrupts, and IRQs | ||
1064 | * assigned to actual devices. | ||
1065 | */ | ||
1066 | static int gsi_to_irq[MAX_GSI_NUM]; | ||
1067 | #else | ||
1068 | |||
1069 | if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) | ||
1070 | return gsi; | ||
1071 | #endif | ||
1072 | |||
1073 | /* Don't set up the ACPI SCI because it's already set up */ | ||
1074 | if (acpi_gbl_FADT.sci_interrupt == gsi) | ||
1075 | return gsi; | ||
1076 | |||
1077 | ioapic = mp_find_ioapic(gsi); | ||
1078 | if (ioapic < 0) { | ||
1079 | printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); | ||
1080 | return gsi; | ||
1081 | } | ||
1082 | |||
1083 | ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; | ||
1084 | |||
1085 | #ifdef CONFIG_X86_32 | ||
1086 | if (ioapic_renumber_irq) | ||
1087 | gsi = ioapic_renumber_irq(ioapic, gsi); | ||
1088 | #endif | ||
1089 | |||
1090 | /* | ||
1091 | * Avoid pin reprogramming. PRTs typically include entries | ||
1092 | * with redundant pin->gsi mappings (but unique PCI devices); | ||
1093 | * we only program the IOAPIC on the first. | ||
1094 | */ | ||
1095 | if (ioapic_pin > MP_MAX_IOAPIC_PIN) { | ||
1096 | printk(KERN_ERR "Invalid reference to IOAPIC pin " | ||
1097 | "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, | ||
1098 | ioapic_pin); | ||
1099 | return gsi; | ||
1100 | } | ||
1101 | if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) { | ||
1102 | Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", | ||
1103 | mp_ioapic_routing[ioapic].apic_id, ioapic_pin); | ||
1104 | #ifdef CONFIG_X86_32 | ||
1105 | return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]); | ||
1106 | #else | ||
1107 | return gsi; | ||
1108 | #endif | ||
1109 | } | ||
1110 | |||
1111 | set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed); | ||
1112 | #ifdef CONFIG_X86_32 | ||
1113 | /* | ||
1114 | * For GSI >= 64, use IRQ compression | ||
1115 | */ | ||
1116 | if ((gsi >= IRQ_COMPRESSION_START) | ||
1117 | && (triggering == ACPI_LEVEL_SENSITIVE)) { | ||
1118 | /* | ||
1119 | * For PCI devices assign IRQs in order, avoiding gaps | ||
1120 | * due to unused I/O APIC pins. | ||
1121 | */ | ||
1122 | int irq = gsi; | ||
1123 | if (gsi < MAX_GSI_NUM) { | ||
1124 | /* | ||
1125 | * Retain the VIA chipset work-around (gsi > 15), but | ||
1126 | * avoid a problem where the 8254 timer (IRQ0) is setup | ||
1127 | * via an override (so it's not on pin 0 of the ioapic), | ||
1128 | * and at the same time, the pin 0 interrupt is a PCI | ||
1129 | * type. The gsi > 15 test could cause these two pins | ||
1130 | * to be shared as IRQ0, and they are not shareable. | ||
1131 | * So test for this condition, and if necessary, avoid | ||
1132 | * the pin collision. | ||
1133 | */ | ||
1134 | gsi = pci_irq++; | ||
1135 | /* | ||
1136 | * Don't assign IRQ used by ACPI SCI | ||
1137 | */ | ||
1138 | if (gsi == acpi_gbl_FADT.sci_interrupt) | ||
1139 | gsi = pci_irq++; | ||
1140 | gsi_to_irq[irq] = gsi; | ||
1141 | } else { | ||
1142 | printk(KERN_ERR "GSI %u is too high\n", gsi); | ||
1143 | return gsi; | ||
1144 | } | ||
1145 | } | ||
1146 | #endif | ||
1147 | io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, | ||
1148 | triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, | ||
1149 | polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | ||
1150 | return gsi; | ||
1151 | } | ||
1152 | |||
849 | /* | 1153 | /* |
850 | * Parse IOAPIC related entries in MADT | 1154 | * Parse IOAPIC related entries in MADT |
851 | * returns 0 on success, < 0 on error | 1155 | * returns 0 on success, < 0 on error |