diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-14 16:43:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-14 16:43:24 -0400 |
commit | a3da5bf84a97d48cfaf66c6842470fc403da5121 (patch) | |
tree | cdf66c0cff8c61eedd60601fc9dffdd1ed39b880 /arch/x86/kernel/acpi/boot.c | |
parent | 3b23e665b68387f5ee7b21f7b75ceea4d9acae4a (diff) | |
parent | d59fdcf2ac501de99c3dfb452af5e254d4342886 (diff) |
Merge branch 'x86/for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86/for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (821 commits)
x86: make 64bit hpet_set_mapping to use ioremap too, v2
x86: get x86_phys_bits early
x86: max_low_pfn_mapped fix #4
x86: change _node_to_cpumask_ptr to return const ptr
x86: I/O APIC: remove an IRQ2-mask hack
x86: fix numaq_tsc_disable calling
x86, e820: remove end_user_pfn
x86: max_low_pfn_mapped fix, #3
x86: max_low_pfn_mapped fix, #2
x86: max_low_pfn_mapped fix, #1
x86_64: fix delayed signals
x86: remove conflicting nx6325 and nx6125 quirks
x86: Recover timer_ack lost in the merge of the NMI watchdog
x86: I/O APIC: Never configure IRQ2
x86: L-APIC: Always fully configure IRQ0
x86: L-APIC: Set IRQ0 as edge-triggered
x86: merge dwarf2 headers
x86: use AS_CFI instead of UNWIND_INFO
x86: use ignore macro instead of hash comment
x86: use matching CFI_ENDPROC
...
Diffstat (limited to 'arch/x86/kernel/acpi/boot.c')
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 442 |
1 files changed, 415 insertions, 27 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 33c5216fd3e1..f489d7a9be92 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <asm/pgtable.h> | 37 | #include <asm/pgtable.h> |
38 | #include <asm/io_apic.h> | 38 | #include <asm/io_apic.h> |
39 | #include <asm/apic.h> | 39 | #include <asm/apic.h> |
40 | #include <asm/genapic.h> | ||
40 | #include <asm/io.h> | 41 | #include <asm/io.h> |
41 | #include <asm/mpspec.h> | 42 | #include <asm/mpspec.h> |
42 | #include <asm/smp.h> | 43 | #include <asm/smp.h> |
@@ -106,21 +107,6 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; | |||
106 | */ | 107 | */ |
107 | enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC; | 108 | enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC; |
108 | 109 | ||
109 | #ifdef CONFIG_X86_64 | ||
110 | |||
111 | /* rely on all ACPI tables being in the direct mapping */ | ||
112 | char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size) | ||
113 | { | ||
114 | if (!phys_addr || !size) | ||
115 | return NULL; | ||
116 | |||
117 | if (phys_addr+size <= (max_pfn_mapped << PAGE_SHIFT) + PAGE_SIZE) | ||
118 | return __va(phys_addr); | ||
119 | |||
120 | return NULL; | ||
121 | } | ||
122 | |||
123 | #else | ||
124 | 110 | ||
125 | /* | 111 | /* |
126 | * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END, | 112 | * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END, |
@@ -139,11 +125,15 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size) | |||
139 | unsigned long base, offset, mapped_size; | 125 | unsigned long base, offset, mapped_size; |
140 | int idx; | 126 | int idx; |
141 | 127 | ||
142 | if (phys + size < 8 * 1024 * 1024) | 128 | if (!phys || !size) |
129 | return NULL; | ||
130 | |||
131 | if (phys+size <= (max_low_pfn_mapped << PAGE_SHIFT)) | ||
143 | return __va(phys); | 132 | return __va(phys); |
144 | 133 | ||
145 | offset = phys & (PAGE_SIZE - 1); | 134 | offset = phys & (PAGE_SIZE - 1); |
146 | mapped_size = PAGE_SIZE - offset; | 135 | mapped_size = PAGE_SIZE - offset; |
136 | clear_fixmap(FIX_ACPI_END); | ||
147 | set_fixmap(FIX_ACPI_END, phys); | 137 | set_fixmap(FIX_ACPI_END, phys); |
148 | base = fix_to_virt(FIX_ACPI_END); | 138 | base = fix_to_virt(FIX_ACPI_END); |
149 | 139 | ||
@@ -155,13 +145,13 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size) | |||
155 | if (--idx < FIX_ACPI_BEGIN) | 145 | if (--idx < FIX_ACPI_BEGIN) |
156 | return NULL; /* cannot handle this */ | 146 | return NULL; /* cannot handle this */ |
157 | phys += PAGE_SIZE; | 147 | phys += PAGE_SIZE; |
148 | clear_fixmap(idx); | ||
158 | set_fixmap(idx, phys); | 149 | set_fixmap(idx, phys); |
159 | mapped_size += PAGE_SIZE; | 150 | mapped_size += PAGE_SIZE; |
160 | } | 151 | } |
161 | 152 | ||
162 | return ((unsigned char *)base + offset); | 153 | return ((unsigned char *)base + offset); |
163 | } | 154 | } |
164 | #endif | ||
165 | 155 | ||
166 | #ifdef CONFIG_PCI_MMCONFIG | 156 | #ifdef CONFIG_PCI_MMCONFIG |
167 | /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ | 157 | /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ |
@@ -338,8 +328,6 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e | |||
338 | 328 | ||
339 | #ifdef CONFIG_X86_IO_APIC | 329 | #ifdef CONFIG_X86_IO_APIC |
340 | 330 | ||
341 | struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS]; | ||
342 | |||
343 | static int __init | 331 | static int __init |
344 | acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end) | 332 | acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end) |
345 | { | 333 | { |
@@ -514,8 +502,6 @@ int acpi_register_gsi(u32 gsi, int triggering, int polarity) | |||
514 | * Make sure all (legacy) PCI IRQs are set as level-triggered. | 502 | * Make sure all (legacy) PCI IRQs are set as level-triggered. |
515 | */ | 503 | */ |
516 | if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) { | 504 | if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) { |
517 | extern void eisa_set_level_irq(unsigned int irq); | ||
518 | |||
519 | if (triggering == ACPI_LEVEL_SENSITIVE) | 505 | if (triggering == ACPI_LEVEL_SENSITIVE) |
520 | eisa_set_level_irq(gsi); | 506 | eisa_set_level_irq(gsi); |
521 | } | 507 | } |
@@ -860,6 +846,364 @@ static int __init acpi_parse_madt_lapic_entries(void) | |||
860 | #endif /* CONFIG_X86_LOCAL_APIC */ | 846 | #endif /* CONFIG_X86_LOCAL_APIC */ |
861 | 847 | ||
862 | #ifdef CONFIG_X86_IO_APIC | 848 | #ifdef CONFIG_X86_IO_APIC |
849 | #define MP_ISA_BUS 0 | ||
850 | |||
851 | #ifdef CONFIG_X86_ES7000 | ||
852 | extern int es7000_plat; | ||
853 | #endif | ||
854 | |||
855 | static struct { | ||
856 | int apic_id; | ||
857 | int gsi_base; | ||
858 | int gsi_end; | ||
859 | DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1); | ||
860 | } mp_ioapic_routing[MAX_IO_APICS]; | ||
861 | |||
862 | static int mp_find_ioapic(int gsi) | ||
863 | { | ||
864 | int i = 0; | ||
865 | |||
866 | /* Find the IOAPIC that manages this GSI. */ | ||
867 | for (i = 0; i < nr_ioapics; i++) { | ||
868 | if ((gsi >= mp_ioapic_routing[i].gsi_base) | ||
869 | && (gsi <= mp_ioapic_routing[i].gsi_end)) | ||
870 | return i; | ||
871 | } | ||
872 | |||
873 | printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); | ||
874 | return -1; | ||
875 | } | ||
876 | |||
877 | static u8 __init uniq_ioapic_id(u8 id) | ||
878 | { | ||
879 | #ifdef CONFIG_X86_32 | ||
880 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && | ||
881 | !APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) | ||
882 | return io_apic_get_unique_id(nr_ioapics, id); | ||
883 | else | ||
884 | return id; | ||
885 | #else | ||
886 | int i; | ||
887 | DECLARE_BITMAP(used, 256); | ||
888 | bitmap_zero(used, 256); | ||
889 | for (i = 0; i < nr_ioapics; i++) { | ||
890 | struct mp_config_ioapic *ia = &mp_ioapics[i]; | ||
891 | __set_bit(ia->mp_apicid, used); | ||
892 | } | ||
893 | if (!test_bit(id, used)) | ||
894 | return id; | ||
895 | return find_first_zero_bit(used, 256); | ||
896 | #endif | ||
897 | } | ||
898 | |||
899 | static int bad_ioapic(unsigned long address) | ||
900 | { | ||
901 | if (nr_ioapics >= MAX_IO_APICS) { | ||
902 | printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " | ||
903 | "(found %d)\n", MAX_IO_APICS, nr_ioapics); | ||
904 | panic("Recompile kernel with bigger MAX_IO_APICS!\n"); | ||
905 | } | ||
906 | if (!address) { | ||
907 | printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address" | ||
908 | " found in table, skipping!\n"); | ||
909 | return 1; | ||
910 | } | ||
911 | return 0; | ||
912 | } | ||
913 | |||
914 | void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) | ||
915 | { | ||
916 | int idx = 0; | ||
917 | |||
918 | if (bad_ioapic(address)) | ||
919 | return; | ||
920 | |||
921 | idx = nr_ioapics; | ||
922 | |||
923 | mp_ioapics[idx].mp_type = MP_IOAPIC; | ||
924 | mp_ioapics[idx].mp_flags = MPC_APIC_USABLE; | ||
925 | mp_ioapics[idx].mp_apicaddr = address; | ||
926 | |||
927 | set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); | ||
928 | mp_ioapics[idx].mp_apicid = uniq_ioapic_id(id); | ||
929 | #ifdef CONFIG_X86_32 | ||
930 | mp_ioapics[idx].mp_apicver = io_apic_get_version(idx); | ||
931 | #else | ||
932 | mp_ioapics[idx].mp_apicver = 0; | ||
933 | #endif | ||
934 | /* | ||
935 | * Build basic GSI lookup table to facilitate gsi->io_apic lookups | ||
936 | * and to prevent reprogramming of IOAPIC pins (PCI GSIs). | ||
937 | */ | ||
938 | mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mp_apicid; | ||
939 | mp_ioapic_routing[idx].gsi_base = gsi_base; | ||
940 | mp_ioapic_routing[idx].gsi_end = gsi_base + | ||
941 | io_apic_get_redir_entries(idx); | ||
942 | |||
943 | printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, " | ||
944 | "GSI %d-%d\n", idx, mp_ioapics[idx].mp_apicid, | ||
945 | mp_ioapics[idx].mp_apicver, mp_ioapics[idx].mp_apicaddr, | ||
946 | mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end); | ||
947 | |||
948 | nr_ioapics++; | ||
949 | } | ||
950 | |||
951 | static void assign_to_mp_irq(struct mp_config_intsrc *m, | ||
952 | struct mp_config_intsrc *mp_irq) | ||
953 | { | ||
954 | memcpy(mp_irq, m, sizeof(struct mp_config_intsrc)); | ||
955 | } | ||
956 | |||
957 | static int mp_irq_cmp(struct mp_config_intsrc *mp_irq, | ||
958 | struct mp_config_intsrc *m) | ||
959 | { | ||
960 | return memcmp(mp_irq, m, sizeof(struct mp_config_intsrc)); | ||
961 | } | ||
962 | |||
963 | static void save_mp_irq(struct mp_config_intsrc *m) | ||
964 | { | ||
965 | int i; | ||
966 | |||
967 | for (i = 0; i < mp_irq_entries; i++) { | ||
968 | if (!mp_irq_cmp(&mp_irqs[i], m)) | ||
969 | return; | ||
970 | } | ||
971 | |||
972 | assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]); | ||
973 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | ||
974 | panic("Max # of irq sources exceeded!!\n"); | ||
975 | } | ||
976 | |||
977 | void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) | ||
978 | { | ||
979 | int ioapic; | ||
980 | int pin; | ||
981 | struct mp_config_intsrc mp_irq; | ||
982 | |||
983 | /* | ||
984 | * Convert 'gsi' to 'ioapic.pin'. | ||
985 | */ | ||
986 | ioapic = mp_find_ioapic(gsi); | ||
987 | if (ioapic < 0) | ||
988 | return; | ||
989 | pin = gsi - mp_ioapic_routing[ioapic].gsi_base; | ||
990 | |||
991 | /* | ||
992 | * TBD: This check is for faulty timer entries, where the override | ||
993 | * erroneously sets the trigger to level, resulting in a HUGE | ||
994 | * increase of timer interrupts! | ||
995 | */ | ||
996 | if ((bus_irq == 0) && (trigger == 3)) | ||
997 | trigger = 1; | ||
998 | |||
999 | mp_irq.mp_type = MP_INTSRC; | ||
1000 | mp_irq.mp_irqtype = mp_INT; | ||
1001 | mp_irq.mp_irqflag = (trigger << 2) | polarity; | ||
1002 | mp_irq.mp_srcbus = MP_ISA_BUS; | ||
1003 | mp_irq.mp_srcbusirq = bus_irq; /* IRQ */ | ||
1004 | mp_irq.mp_dstapic = mp_ioapics[ioapic].mp_apicid; /* APIC ID */ | ||
1005 | mp_irq.mp_dstirq = pin; /* INTIN# */ | ||
1006 | |||
1007 | save_mp_irq(&mp_irq); | ||
1008 | } | ||
1009 | |||
1010 | void __init mp_config_acpi_legacy_irqs(void) | ||
1011 | { | ||
1012 | int i; | ||
1013 | int ioapic; | ||
1014 | unsigned int dstapic; | ||
1015 | struct mp_config_intsrc mp_irq; | ||
1016 | |||
1017 | #if defined (CONFIG_MCA) || defined (CONFIG_EISA) | ||
1018 | /* | ||
1019 | * Fabricate the legacy ISA bus (bus #31). | ||
1020 | */ | ||
1021 | mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; | ||
1022 | #endif | ||
1023 | set_bit(MP_ISA_BUS, mp_bus_not_pci); | ||
1024 | Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); | ||
1025 | |||
1026 | #ifdef CONFIG_X86_ES7000 | ||
1027 | /* | ||
1028 | * Older generations of ES7000 have no legacy identity mappings | ||
1029 | */ | ||
1030 | if (es7000_plat == 1) | ||
1031 | return; | ||
1032 | #endif | ||
1033 | |||
1034 | /* | ||
1035 | * Locate the IOAPIC that manages the ISA IRQs (0-15). | ||
1036 | */ | ||
1037 | ioapic = mp_find_ioapic(0); | ||
1038 | if (ioapic < 0) | ||
1039 | return; | ||
1040 | dstapic = mp_ioapics[ioapic].mp_apicid; | ||
1041 | |||
1042 | /* | ||
1043 | * Use the default configuration for the IRQs 0-15. Unless | ||
1044 | * overridden by (MADT) interrupt source override entries. | ||
1045 | */ | ||
1046 | for (i = 0; i < 16; i++) { | ||
1047 | int idx; | ||
1048 | |||
1049 | for (idx = 0; idx < mp_irq_entries; idx++) { | ||
1050 | struct mp_config_intsrc *irq = mp_irqs + idx; | ||
1051 | |||
1052 | /* Do we already have a mapping for this ISA IRQ? */ | ||
1053 | if (irq->mp_srcbus == MP_ISA_BUS | ||
1054 | && irq->mp_srcbusirq == i) | ||
1055 | break; | ||
1056 | |||
1057 | /* Do we already have a mapping for this IOAPIC pin */ | ||
1058 | if (irq->mp_dstapic == dstapic && | ||
1059 | irq->mp_dstirq == i) | ||
1060 | break; | ||
1061 | } | ||
1062 | |||
1063 | if (idx != mp_irq_entries) { | ||
1064 | printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i); | ||
1065 | continue; /* IRQ already used */ | ||
1066 | } | ||
1067 | |||
1068 | mp_irq.mp_type = MP_INTSRC; | ||
1069 | mp_irq.mp_irqflag = 0; /* Conforming */ | ||
1070 | mp_irq.mp_srcbus = MP_ISA_BUS; | ||
1071 | mp_irq.mp_dstapic = dstapic; | ||
1072 | mp_irq.mp_irqtype = mp_INT; | ||
1073 | mp_irq.mp_srcbusirq = i; /* Identity mapped */ | ||
1074 | mp_irq.mp_dstirq = i; | ||
1075 | |||
1076 | save_mp_irq(&mp_irq); | ||
1077 | } | ||
1078 | } | ||
1079 | |||
1080 | int mp_register_gsi(u32 gsi, int triggering, int polarity) | ||
1081 | { | ||
1082 | int ioapic; | ||
1083 | int ioapic_pin; | ||
1084 | #ifdef CONFIG_X86_32 | ||
1085 | #define MAX_GSI_NUM 4096 | ||
1086 | #define IRQ_COMPRESSION_START 64 | ||
1087 | |||
1088 | static int pci_irq = IRQ_COMPRESSION_START; | ||
1089 | /* | ||
1090 | * Mapping between Global System Interrupts, which | ||
1091 | * represent all possible interrupts, and IRQs | ||
1092 | * assigned to actual devices. | ||
1093 | */ | ||
1094 | static int gsi_to_irq[MAX_GSI_NUM]; | ||
1095 | #else | ||
1096 | |||
1097 | if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) | ||
1098 | return gsi; | ||
1099 | #endif | ||
1100 | |||
1101 | /* Don't set up the ACPI SCI because it's already set up */ | ||
1102 | if (acpi_gbl_FADT.sci_interrupt == gsi) | ||
1103 | return gsi; | ||
1104 | |||
1105 | ioapic = mp_find_ioapic(gsi); | ||
1106 | if (ioapic < 0) { | ||
1107 | printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); | ||
1108 | return gsi; | ||
1109 | } | ||
1110 | |||
1111 | ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; | ||
1112 | |||
1113 | #ifdef CONFIG_X86_32 | ||
1114 | if (ioapic_renumber_irq) | ||
1115 | gsi = ioapic_renumber_irq(ioapic, gsi); | ||
1116 | #endif | ||
1117 | |||
1118 | /* | ||
1119 | * Avoid pin reprogramming. PRTs typically include entries | ||
1120 | * with redundant pin->gsi mappings (but unique PCI devices); | ||
1121 | * we only program the IOAPIC on the first. | ||
1122 | */ | ||
1123 | if (ioapic_pin > MP_MAX_IOAPIC_PIN) { | ||
1124 | printk(KERN_ERR "Invalid reference to IOAPIC pin " | ||
1125 | "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, | ||
1126 | ioapic_pin); | ||
1127 | return gsi; | ||
1128 | } | ||
1129 | if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) { | ||
1130 | Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", | ||
1131 | mp_ioapic_routing[ioapic].apic_id, ioapic_pin); | ||
1132 | #ifdef CONFIG_X86_32 | ||
1133 | return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]); | ||
1134 | #else | ||
1135 | return gsi; | ||
1136 | #endif | ||
1137 | } | ||
1138 | |||
1139 | set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed); | ||
1140 | #ifdef CONFIG_X86_32 | ||
1141 | /* | ||
1142 | * For GSI >= 64, use IRQ compression | ||
1143 | */ | ||
1144 | if ((gsi >= IRQ_COMPRESSION_START) | ||
1145 | && (triggering == ACPI_LEVEL_SENSITIVE)) { | ||
1146 | /* | ||
1147 | * For PCI devices assign IRQs in order, avoiding gaps | ||
1148 | * due to unused I/O APIC pins. | ||
1149 | */ | ||
1150 | int irq = gsi; | ||
1151 | if (gsi < MAX_GSI_NUM) { | ||
1152 | /* | ||
1153 | * Retain the VIA chipset work-around (gsi > 15), but | ||
1154 | * avoid a problem where the 8254 timer (IRQ0) is setup | ||
1155 | * via an override (so it's not on pin 0 of the ioapic), | ||
1156 | * and at the same time, the pin 0 interrupt is a PCI | ||
1157 | * type. The gsi > 15 test could cause these two pins | ||
1158 | * to be shared as IRQ0, and they are not shareable. | ||
1159 | * So test for this condition, and if necessary, avoid | ||
1160 | * the pin collision. | ||
1161 | */ | ||
1162 | gsi = pci_irq++; | ||
1163 | /* | ||
1164 | * Don't assign IRQ used by ACPI SCI | ||
1165 | */ | ||
1166 | if (gsi == acpi_gbl_FADT.sci_interrupt) | ||
1167 | gsi = pci_irq++; | ||
1168 | gsi_to_irq[irq] = gsi; | ||
1169 | } else { | ||
1170 | printk(KERN_ERR "GSI %u is too high\n", gsi); | ||
1171 | return gsi; | ||
1172 | } | ||
1173 | } | ||
1174 | #endif | ||
1175 | io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, | ||
1176 | triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, | ||
1177 | polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | ||
1178 | return gsi; | ||
1179 | } | ||
1180 | |||
1181 | int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, | ||
1182 | u32 gsi, int triggering, int polarity) | ||
1183 | { | ||
1184 | #ifdef CONFIG_X86_MPPARSE | ||
1185 | struct mp_config_intsrc mp_irq; | ||
1186 | int ioapic; | ||
1187 | |||
1188 | if (!acpi_ioapic) | ||
1189 | return 0; | ||
1190 | |||
1191 | /* print the entry should happen on mptable identically */ | ||
1192 | mp_irq.mp_type = MP_INTSRC; | ||
1193 | mp_irq.mp_irqtype = mp_INT; | ||
1194 | mp_irq.mp_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) | | ||
1195 | (polarity == ACPI_ACTIVE_HIGH ? 1 : 3); | ||
1196 | mp_irq.mp_srcbus = number; | ||
1197 | mp_irq.mp_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3); | ||
1198 | ioapic = mp_find_ioapic(gsi); | ||
1199 | mp_irq.mp_dstapic = mp_ioapic_routing[ioapic].apic_id; | ||
1200 | mp_irq.mp_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base; | ||
1201 | |||
1202 | save_mp_irq(&mp_irq); | ||
1203 | #endif | ||
1204 | return 0; | ||
1205 | } | ||
1206 | |||
863 | /* | 1207 | /* |
864 | * Parse IOAPIC related entries in MADT | 1208 | * Parse IOAPIC related entries in MADT |
865 | * returns 0 on success, < 0 on error | 1209 | * returns 0 on success, < 0 on error |
@@ -1009,8 +1353,6 @@ static void __init acpi_process_madt(void) | |||
1009 | return; | 1353 | return; |
1010 | } | 1354 | } |
1011 | 1355 | ||
1012 | #ifdef __i386__ | ||
1013 | |||
1014 | static int __init disable_acpi_irq(const struct dmi_system_id *d) | 1356 | static int __init disable_acpi_irq(const struct dmi_system_id *d) |
1015 | { | 1357 | { |
1016 | if (!acpi_force) { | 1358 | if (!acpi_force) { |
@@ -1061,6 +1403,16 @@ static int __init force_acpi_ht(const struct dmi_system_id *d) | |||
1061 | } | 1403 | } |
1062 | 1404 | ||
1063 | /* | 1405 | /* |
1406 | * Force ignoring BIOS IRQ0 pin2 override | ||
1407 | */ | ||
1408 | static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d) | ||
1409 | { | ||
1410 | pr_notice("%s detected: Ignoring BIOS IRQ0 pin2 override\n", d->ident); | ||
1411 | acpi_skip_timer_override = 1; | ||
1412 | return 0; | ||
1413 | } | ||
1414 | |||
1415 | /* | ||
1064 | * If your system is blacklisted here, but you find that acpi=force | 1416 | * If your system is blacklisted here, but you find that acpi=force |
1065 | * works for you, please contact acpi-devel@sourceforge.net | 1417 | * works for you, please contact acpi-devel@sourceforge.net |
1066 | */ | 1418 | */ |
@@ -1227,11 +1579,35 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = { | |||
1227 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), | 1579 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), |
1228 | }, | 1580 | }, |
1229 | }, | 1581 | }, |
1582 | /* | ||
1583 | * HP laptops which use a DSDT reporting as HP/SB400/10000, | ||
1584 | * which includes some code which overrides all temperature | ||
1585 | * trip points to 16C if the INTIN2 input of the I/O APIC | ||
1586 | * is enabled. This input is incorrectly designated the | ||
1587 | * ISA IRQ 0 via an interrupt source override even though | ||
1588 | * it is wired to the output of the master 8259A and INTIN0 | ||
1589 | * is not connected at all. Force ignoring BIOS IRQ0 pin2 | ||
1590 | * override in that cases. | ||
1591 | */ | ||
1592 | { | ||
1593 | .callback = dmi_ignore_irq0_timer_override, | ||
1594 | .ident = "HP NX6125 laptop", | ||
1595 | .matches = { | ||
1596 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
1597 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6125"), | ||
1598 | }, | ||
1599 | }, | ||
1600 | { | ||
1601 | .callback = dmi_ignore_irq0_timer_override, | ||
1602 | .ident = "HP NX6325 laptop", | ||
1603 | .matches = { | ||
1604 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
1605 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"), | ||
1606 | }, | ||
1607 | }, | ||
1230 | {} | 1608 | {} |
1231 | }; | 1609 | }; |
1232 | 1610 | ||
1233 | #endif /* __i386__ */ | ||
1234 | |||
1235 | /* | 1611 | /* |
1236 | * acpi_boot_table_init() and acpi_boot_init() | 1612 | * acpi_boot_table_init() and acpi_boot_init() |
1237 | * called from setup_arch(), always. | 1613 | * called from setup_arch(), always. |
@@ -1259,9 +1635,7 @@ int __init acpi_boot_table_init(void) | |||
1259 | { | 1635 | { |
1260 | int error; | 1636 | int error; |
1261 | 1637 | ||
1262 | #ifdef __i386__ | ||
1263 | dmi_check_system(acpi_dmi_table); | 1638 | dmi_check_system(acpi_dmi_table); |
1264 | #endif | ||
1265 | 1639 | ||
1266 | /* | 1640 | /* |
1267 | * If acpi_disabled, bail out | 1641 | * If acpi_disabled, bail out |
@@ -1386,6 +1760,20 @@ static int __init parse_pci(char *arg) | |||
1386 | } | 1760 | } |
1387 | early_param("pci", parse_pci); | 1761 | early_param("pci", parse_pci); |
1388 | 1762 | ||
1763 | int __init acpi_mps_check(void) | ||
1764 | { | ||
1765 | #if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_X86_MPPARSE) | ||
1766 | /* mptable code is not built-in*/ | ||
1767 | if (acpi_disabled || acpi_noirq) { | ||
1768 | printk(KERN_WARNING "MPS support code is not built-in.\n" | ||
1769 | "Using acpi=off or acpi=noirq or pci=noacpi " | ||
1770 | "may have problem\n"); | ||
1771 | return 1; | ||
1772 | } | ||
1773 | #endif | ||
1774 | return 0; | ||
1775 | } | ||
1776 | |||
1389 | #ifdef CONFIG_X86_IO_APIC | 1777 | #ifdef CONFIG_X86_IO_APIC |
1390 | static int __init parse_acpi_skip_timer_override(char *arg) | 1778 | static int __init parse_acpi_skip_timer_override(char *arg) |
1391 | { | 1779 | { |