diff options
-rw-r--r-- | arch/x86/Kconfig | 12 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 12 | ||||
-rw-r--r-- | arch/x86/kernel/apic/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/kernel/apic/es7000_32.c | 738 |
4 files changed, 2 insertions, 761 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 0af5250d914f..c6a864748c38 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -351,7 +351,6 @@ config X86_EXTENDED_PLATFORM | |||
351 | SGI 320/540 (Visual Workstation) | 351 | SGI 320/540 (Visual Workstation) |
352 | STA2X11-based (e.g. Northville) | 352 | STA2X11-based (e.g. Northville) |
353 | Summit/EXA (IBM x440) | 353 | Summit/EXA (IBM x440) |
354 | Unisys ES7000 IA32 series | ||
355 | Moorestown MID devices | 354 | Moorestown MID devices |
356 | 355 | ||
357 | If you have one of these systems, or if you want to build a | 356 | If you have one of these systems, or if you want to build a |
@@ -489,7 +488,7 @@ config X86_32_NON_STANDARD | |||
489 | depends on X86_32 && SMP | 488 | depends on X86_32 && SMP |
490 | depends on X86_EXTENDED_PLATFORM | 489 | depends on X86_EXTENDED_PLATFORM |
491 | ---help--- | 490 | ---help--- |
492 | This option compiles in the NUMAQ, Summit, bigsmp, ES7000, | 491 | This option compiles in the NUMAQ, Summit, bigsmp, |
493 | STA2X11, default subarchitectures. It is intended for a generic | 492 | STA2X11, default subarchitectures. It is intended for a generic |
494 | binary kernel. If you select them all, kernel will probe it | 493 | binary kernel. If you select them all, kernel will probe it |
495 | one by one and will fallback to default. | 494 | one by one and will fallback to default. |
@@ -555,13 +554,6 @@ config X86_SUMMIT | |||
555 | This option is needed for IBM systems that use the Summit/EXA chipset. | 554 | This option is needed for IBM systems that use the Summit/EXA chipset. |
556 | In particular, it is needed for the x440. | 555 | In particular, it is needed for the x440. |
557 | 556 | ||
558 | config X86_ES7000 | ||
559 | bool "Unisys ES7000 IA32 series" | ||
560 | depends on X86_32_NON_STANDARD && X86_BIGSMP | ||
561 | ---help--- | ||
562 | Support for Unisys ES7000 systems. Say 'Y' here if this kernel is | ||
563 | supposed to run on an IA32-based Unisys ES7000 system. | ||
564 | |||
565 | config X86_32_IRIS | 557 | config X86_32_IRIS |
566 | tristate "Eurobraille/Iris poweroff module" | 558 | tristate "Eurobraille/Iris poweroff module" |
567 | depends on X86_32 | 559 | depends on X86_32 |
@@ -820,7 +812,7 @@ config NR_CPUS | |||
820 | range 2 8192 if SMP && !MAXSMP && CPUMASK_OFFSTACK && X86_64 | 812 | range 2 8192 if SMP && !MAXSMP && CPUMASK_OFFSTACK && X86_64 |
821 | default "1" if !SMP | 813 | default "1" if !SMP |
822 | default "8192" if MAXSMP | 814 | default "8192" if MAXSMP |
823 | default "32" if SMP && (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000) | 815 | default "32" if SMP && (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP) |
824 | default "8" if SMP | 816 | default "8" if SMP |
825 | ---help--- | 817 | ---help--- |
826 | This allows you to specify the maximum number of CPUs which this | 818 | This allows you to specify the maximum number of CPUs which this |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 1dac94265b59..bcdace45b000 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -907,10 +907,6 @@ static int __init acpi_parse_madt_lapic_entries(void) | |||
907 | #ifdef CONFIG_X86_IO_APIC | 907 | #ifdef CONFIG_X86_IO_APIC |
908 | #define MP_ISA_BUS 0 | 908 | #define MP_ISA_BUS 0 |
909 | 909 | ||
910 | #ifdef CONFIG_X86_ES7000 | ||
911 | extern int es7000_plat; | ||
912 | #endif | ||
913 | |||
914 | void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) | 910 | void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) |
915 | { | 911 | { |
916 | int ioapic; | 912 | int ioapic; |
@@ -960,14 +956,6 @@ void __init mp_config_acpi_legacy_irqs(void) | |||
960 | set_bit(MP_ISA_BUS, mp_bus_not_pci); | 956 | set_bit(MP_ISA_BUS, mp_bus_not_pci); |
961 | pr_debug("Bus #%d is ISA\n", MP_ISA_BUS); | 957 | pr_debug("Bus #%d is ISA\n", MP_ISA_BUS); |
962 | 958 | ||
963 | #ifdef CONFIG_X86_ES7000 | ||
964 | /* | ||
965 | * Older generations of ES7000 have no legacy identity mappings | ||
966 | */ | ||
967 | if (es7000_plat == 1) | ||
968 | return; | ||
969 | #endif | ||
970 | |||
971 | /* | 959 | /* |
972 | * Use the default configuration for the IRQs 0-15. Unless | 960 | * Use the default configuration for the IRQs 0-15. Unless |
973 | * overridden by (MADT) interrupt source override entries. | 961 | * overridden by (MADT) interrupt source override entries. |
diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile index 0ae0323b1f9c..7b600c68ed20 100644 --- a/arch/x86/kernel/apic/Makefile +++ b/arch/x86/kernel/apic/Makefile | |||
@@ -21,7 +21,6 @@ endif | |||
21 | obj-$(CONFIG_X86_NUMAQ) += numaq_32.o | 21 | obj-$(CONFIG_X86_NUMAQ) += numaq_32.o |
22 | obj-$(CONFIG_X86_SUMMIT) += summit_32.o | 22 | obj-$(CONFIG_X86_SUMMIT) += summit_32.o |
23 | obj-$(CONFIG_X86_BIGSMP) += bigsmp_32.o | 23 | obj-$(CONFIG_X86_BIGSMP) += bigsmp_32.o |
24 | obj-$(CONFIG_X86_ES7000) += es7000_32.o | ||
25 | 24 | ||
26 | # For 32bit, probe_32 need to be listed last | 25 | # For 32bit, probe_32 need to be listed last |
27 | obj-$(CONFIG_X86_LOCAL_APIC) += probe_$(BITS).o | 26 | obj-$(CONFIG_X86_LOCAL_APIC) += probe_$(BITS).o |
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c deleted file mode 100644 index 6f8f8b348a39..000000000000 --- a/arch/x86/kernel/apic/es7000_32.c +++ /dev/null | |||
@@ -1,738 +0,0 @@ | |||
1 | /* | ||
2 | * Written by: Garry Forsgren, Unisys Corporation | ||
3 | * Natalie Protasevich, Unisys Corporation | ||
4 | * | ||
5 | * This file contains the code to configure and interface | ||
6 | * with Unisys ES7000 series hardware system manager. | ||
7 | * | ||
8 | * Copyright (c) 2003 Unisys Corporation. | ||
9 | * Copyright (C) 2009, Red Hat, Inc., Ingo Molnar | ||
10 | * | ||
11 | * All Rights Reserved. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of version 2 of the GNU General Public License as | ||
15 | * published by the Free Software Foundation. | ||
16 | * | ||
17 | * This program is distributed in the hope that it would be useful, but | ||
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License along | ||
22 | * with this program; if not, write the Free Software Foundation, Inc., 59 | ||
23 | * Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
24 | * | ||
25 | * Contact information: Unisys Corporation, Township Line & Union Meeting | ||
26 | * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or: | ||
27 | * | ||
28 | * http://www.unisys.com | ||
29 | */ | ||
30 | |||
31 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
32 | |||
33 | #include <linux/notifier.h> | ||
34 | #include <linux/spinlock.h> | ||
35 | #include <linux/cpumask.h> | ||
36 | #include <linux/threads.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/reboot.h> | ||
40 | #include <linux/string.h> | ||
41 | #include <linux/types.h> | ||
42 | #include <linux/errno.h> | ||
43 | #include <linux/acpi.h> | ||
44 | #include <linux/init.h> | ||
45 | #include <linux/gfp.h> | ||
46 | #include <linux/nmi.h> | ||
47 | #include <linux/smp.h> | ||
48 | #include <linux/io.h> | ||
49 | |||
50 | #include <asm/apicdef.h> | ||
51 | #include <linux/atomic.h> | ||
52 | #include <asm/fixmap.h> | ||
53 | #include <asm/mpspec.h> | ||
54 | #include <asm/setup.h> | ||
55 | #include <asm/apic.h> | ||
56 | #include <asm/ipi.h> | ||
57 | |||
58 | /* | ||
59 | * ES7000 chipsets | ||
60 | */ | ||
61 | |||
62 | #define NON_UNISYS 0 | ||
63 | #define ES7000_CLASSIC 1 | ||
64 | #define ES7000_ZORRO 2 | ||
65 | |||
66 | #define MIP_REG 1 | ||
67 | #define MIP_PSAI_REG 4 | ||
68 | |||
69 | #define MIP_BUSY 1 | ||
70 | #define MIP_SPIN 0xf0000 | ||
71 | #define MIP_VALID 0x0100000000000000ULL | ||
72 | #define MIP_SW_APIC 0x1020b | ||
73 | |||
74 | #define MIP_PORT(val) ((val >> 32) & 0xffff) | ||
75 | |||
76 | #define MIP_RD_LO(val) (val & 0xffffffff) | ||
77 | |||
78 | struct mip_reg { | ||
79 | unsigned long long off_0x00; | ||
80 | unsigned long long off_0x08; | ||
81 | unsigned long long off_0x10; | ||
82 | unsigned long long off_0x18; | ||
83 | unsigned long long off_0x20; | ||
84 | unsigned long long off_0x28; | ||
85 | unsigned long long off_0x30; | ||
86 | unsigned long long off_0x38; | ||
87 | }; | ||
88 | |||
89 | struct mip_reg_info { | ||
90 | unsigned long long mip_info; | ||
91 | unsigned long long delivery_info; | ||
92 | unsigned long long host_reg; | ||
93 | unsigned long long mip_reg; | ||
94 | }; | ||
95 | |||
96 | struct psai { | ||
97 | unsigned long long entry_type; | ||
98 | unsigned long long addr; | ||
99 | unsigned long long bep_addr; | ||
100 | }; | ||
101 | |||
102 | #ifdef CONFIG_ACPI | ||
103 | |||
104 | struct es7000_oem_table { | ||
105 | struct acpi_table_header Header; | ||
106 | u32 OEMTableAddr; | ||
107 | u32 OEMTableSize; | ||
108 | }; | ||
109 | |||
110 | static unsigned long oem_addrX; | ||
111 | static unsigned long oem_size; | ||
112 | |||
113 | #endif | ||
114 | |||
115 | /* | ||
116 | * ES7000 Globals | ||
117 | */ | ||
118 | |||
119 | static volatile unsigned long *psai; | ||
120 | static struct mip_reg *mip_reg; | ||
121 | static struct mip_reg *host_reg; | ||
122 | static int mip_port; | ||
123 | static unsigned long mip_addr; | ||
124 | static unsigned long host_addr; | ||
125 | |||
126 | int es7000_plat; | ||
127 | |||
128 | /* | ||
129 | * GSI override for ES7000 platforms. | ||
130 | */ | ||
131 | |||
132 | |||
133 | static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip) | ||
134 | { | ||
135 | unsigned long vect = 0, psaival = 0; | ||
136 | |||
137 | if (psai == NULL) | ||
138 | return -1; | ||
139 | |||
140 | vect = ((unsigned long)__pa(eip)/0x1000) << 16; | ||
141 | psaival = (0x1000000 | vect | cpu); | ||
142 | |||
143 | while (*psai & 0x1000000) | ||
144 | ; | ||
145 | |||
146 | *psai = psaival; | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static int es7000_apic_is_cluster(void) | ||
152 | { | ||
153 | /* MPENTIUMIII */ | ||
154 | if (boot_cpu_data.x86 == 6 && | ||
155 | (boot_cpu_data.x86_model >= 7 && boot_cpu_data.x86_model <= 11)) | ||
156 | return 1; | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static void setup_unisys(void) | ||
162 | { | ||
163 | /* | ||
164 | * Determine the generation of the ES7000 currently running. | ||
165 | * | ||
166 | * es7000_plat = 1 if the machine is a 5xx ES7000 box | ||
167 | * es7000_plat = 2 if the machine is a x86_64 ES7000 box | ||
168 | * | ||
169 | */ | ||
170 | if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2)) | ||
171 | es7000_plat = ES7000_ZORRO; | ||
172 | else | ||
173 | es7000_plat = ES7000_CLASSIC; | ||
174 | } | ||
175 | |||
176 | /* | ||
177 | * Parse the OEM Table: | ||
178 | */ | ||
179 | static int parse_unisys_oem(char *oemptr) | ||
180 | { | ||
181 | int i; | ||
182 | int success = 0; | ||
183 | unsigned char type, size; | ||
184 | unsigned long val; | ||
185 | char *tp = NULL; | ||
186 | struct psai *psaip = NULL; | ||
187 | struct mip_reg_info *mi; | ||
188 | struct mip_reg *host, *mip; | ||
189 | |||
190 | tp = oemptr; | ||
191 | |||
192 | tp += 8; | ||
193 | |||
194 | for (i = 0; i <= 6; i++) { | ||
195 | type = *tp++; | ||
196 | size = *tp++; | ||
197 | tp -= 2; | ||
198 | switch (type) { | ||
199 | case MIP_REG: | ||
200 | mi = (struct mip_reg_info *)tp; | ||
201 | val = MIP_RD_LO(mi->host_reg); | ||
202 | host_addr = val; | ||
203 | host = (struct mip_reg *)val; | ||
204 | host_reg = __va(host); | ||
205 | val = MIP_RD_LO(mi->mip_reg); | ||
206 | mip_port = MIP_PORT(mi->mip_info); | ||
207 | mip_addr = val; | ||
208 | mip = (struct mip_reg *)val; | ||
209 | mip_reg = __va(mip); | ||
210 | pr_debug("host_reg = 0x%lx\n", | ||
211 | (unsigned long)host_reg); | ||
212 | pr_debug("mip_reg = 0x%lx\n", | ||
213 | (unsigned long)mip_reg); | ||
214 | success++; | ||
215 | break; | ||
216 | case MIP_PSAI_REG: | ||
217 | psaip = (struct psai *)tp; | ||
218 | if (tp != NULL) { | ||
219 | if (psaip->addr) | ||
220 | psai = __va(psaip->addr); | ||
221 | else | ||
222 | psai = NULL; | ||
223 | success++; | ||
224 | } | ||
225 | break; | ||
226 | default: | ||
227 | break; | ||
228 | } | ||
229 | tp += size; | ||
230 | } | ||
231 | |||
232 | if (success < 2) | ||
233 | es7000_plat = NON_UNISYS; | ||
234 | else | ||
235 | setup_unisys(); | ||
236 | |||
237 | return es7000_plat; | ||
238 | } | ||
239 | |||
240 | #ifdef CONFIG_ACPI | ||
241 | static int __init find_unisys_acpi_oem_table(unsigned long *oem_addr) | ||
242 | { | ||
243 | struct acpi_table_header *header = NULL; | ||
244 | struct es7000_oem_table *table; | ||
245 | acpi_size tbl_size; | ||
246 | acpi_status ret; | ||
247 | int i = 0; | ||
248 | |||
249 | for (;;) { | ||
250 | ret = acpi_get_table_with_size("OEM1", i++, &header, &tbl_size); | ||
251 | if (!ACPI_SUCCESS(ret)) | ||
252 | return -1; | ||
253 | |||
254 | if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) | ||
255 | break; | ||
256 | |||
257 | early_acpi_os_unmap_memory(header, tbl_size); | ||
258 | } | ||
259 | |||
260 | table = (void *)header; | ||
261 | |||
262 | oem_addrX = table->OEMTableAddr; | ||
263 | oem_size = table->OEMTableSize; | ||
264 | |||
265 | early_acpi_os_unmap_memory(header, tbl_size); | ||
266 | |||
267 | *oem_addr = (unsigned long)__acpi_map_table(oem_addrX, oem_size); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr) | ||
273 | { | ||
274 | if (!oem_addr) | ||
275 | return; | ||
276 | |||
277 | __acpi_unmap_table((char *)oem_addr, oem_size); | ||
278 | } | ||
279 | |||
280 | static int es7000_check_dsdt(void) | ||
281 | { | ||
282 | struct acpi_table_header header; | ||
283 | |||
284 | if (ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_DSDT, 0, &header)) && | ||
285 | !strncmp(header.oem_id, "UNISYS", 6)) | ||
286 | return 1; | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static int es7000_acpi_ret; | ||
291 | |||
292 | /* Hook from generic ACPI tables.c */ | ||
293 | static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | ||
294 | { | ||
295 | unsigned long oem_addr = 0; | ||
296 | int check_dsdt; | ||
297 | int ret = 0; | ||
298 | |||
299 | /* check dsdt at first to avoid clear fix_map for oem_addr */ | ||
300 | check_dsdt = es7000_check_dsdt(); | ||
301 | |||
302 | if (!find_unisys_acpi_oem_table(&oem_addr)) { | ||
303 | if (check_dsdt) { | ||
304 | ret = parse_unisys_oem((char *)oem_addr); | ||
305 | } else { | ||
306 | setup_unisys(); | ||
307 | ret = 1; | ||
308 | } | ||
309 | /* | ||
310 | * we need to unmap it | ||
311 | */ | ||
312 | unmap_unisys_acpi_oem_table(oem_addr); | ||
313 | } | ||
314 | |||
315 | es7000_acpi_ret = ret; | ||
316 | |||
317 | return ret && !es7000_apic_is_cluster(); | ||
318 | } | ||
319 | |||
320 | static int es7000_acpi_madt_oem_check_cluster(char *oem_id, char *oem_table_id) | ||
321 | { | ||
322 | int ret = es7000_acpi_ret; | ||
323 | |||
324 | return ret && es7000_apic_is_cluster(); | ||
325 | } | ||
326 | |||
327 | #else /* !CONFIG_ACPI: */ | ||
328 | static int es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | ||
329 | { | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | static int es7000_acpi_madt_oem_check_cluster(char *oem_id, char *oem_table_id) | ||
334 | { | ||
335 | return 0; | ||
336 | } | ||
337 | #endif /* !CONFIG_ACPI */ | ||
338 | |||
339 | static void es7000_spin(int n) | ||
340 | { | ||
341 | int i = 0; | ||
342 | |||
343 | while (i++ < n) | ||
344 | rep_nop(); | ||
345 | } | ||
346 | |||
347 | static int es7000_mip_write(struct mip_reg *mip_reg) | ||
348 | { | ||
349 | int status = 0; | ||
350 | int spin; | ||
351 | |||
352 | spin = MIP_SPIN; | ||
353 | while ((host_reg->off_0x38 & MIP_VALID) != 0) { | ||
354 | if (--spin <= 0) { | ||
355 | WARN(1, "Timeout waiting for Host Valid Flag\n"); | ||
356 | return -1; | ||
357 | } | ||
358 | es7000_spin(MIP_SPIN); | ||
359 | } | ||
360 | |||
361 | memcpy(host_reg, mip_reg, sizeof(struct mip_reg)); | ||
362 | outb(1, mip_port); | ||
363 | |||
364 | spin = MIP_SPIN; | ||
365 | |||
366 | while ((mip_reg->off_0x38 & MIP_VALID) == 0) { | ||
367 | if (--spin <= 0) { | ||
368 | WARN(1, "Timeout waiting for MIP Valid Flag\n"); | ||
369 | return -1; | ||
370 | } | ||
371 | es7000_spin(MIP_SPIN); | ||
372 | } | ||
373 | |||
374 | status = (mip_reg->off_0x00 & 0xffff0000000000ULL) >> 48; | ||
375 | mip_reg->off_0x38 &= ~MIP_VALID; | ||
376 | |||
377 | return status; | ||
378 | } | ||
379 | |||
380 | static void es7000_enable_apic_mode(void) | ||
381 | { | ||
382 | struct mip_reg es7000_mip_reg; | ||
383 | int mip_status; | ||
384 | |||
385 | if (!es7000_plat) | ||
386 | return; | ||
387 | |||
388 | pr_info("Enabling APIC mode.\n"); | ||
389 | memset(&es7000_mip_reg, 0, sizeof(struct mip_reg)); | ||
390 | es7000_mip_reg.off_0x00 = MIP_SW_APIC; | ||
391 | es7000_mip_reg.off_0x38 = MIP_VALID; | ||
392 | |||
393 | while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0) | ||
394 | WARN(1, "Command failed, status = %x\n", mip_status); | ||
395 | } | ||
396 | |||
397 | static unsigned int es7000_get_apic_id(unsigned long x) | ||
398 | { | ||
399 | return (x >> 24) & 0xFF; | ||
400 | } | ||
401 | |||
402 | static void es7000_send_IPI_mask(const struct cpumask *mask, int vector) | ||
403 | { | ||
404 | default_send_IPI_mask_sequence_phys(mask, vector); | ||
405 | } | ||
406 | |||
407 | static void es7000_send_IPI_allbutself(int vector) | ||
408 | { | ||
409 | default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); | ||
410 | } | ||
411 | |||
412 | static void es7000_send_IPI_all(int vector) | ||
413 | { | ||
414 | es7000_send_IPI_mask(cpu_online_mask, vector); | ||
415 | } | ||
416 | |||
417 | static int es7000_apic_id_registered(void) | ||
418 | { | ||
419 | return 1; | ||
420 | } | ||
421 | |||
422 | static const struct cpumask *target_cpus_cluster(void) | ||
423 | { | ||
424 | return cpu_all_mask; | ||
425 | } | ||
426 | |||
427 | static const struct cpumask *es7000_target_cpus(void) | ||
428 | { | ||
429 | return cpumask_of(smp_processor_id()); | ||
430 | } | ||
431 | |||
432 | static unsigned long es7000_check_apicid_used(physid_mask_t *map, int apicid) | ||
433 | { | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static unsigned long es7000_check_apicid_present(int bit) | ||
438 | { | ||
439 | return physid_isset(bit, phys_cpu_present_map); | ||
440 | } | ||
441 | |||
442 | static int es7000_early_logical_apicid(int cpu) | ||
443 | { | ||
444 | /* on es7000, logical apicid is the same as physical */ | ||
445 | return early_per_cpu(x86_bios_cpu_apicid, cpu); | ||
446 | } | ||
447 | |||
448 | static unsigned long calculate_ldr(int cpu) | ||
449 | { | ||
450 | unsigned long id = per_cpu(x86_bios_cpu_apicid, cpu); | ||
451 | |||
452 | return SET_APIC_LOGICAL_ID(id); | ||
453 | } | ||
454 | |||
455 | /* | ||
456 | * Set up the logical destination ID. | ||
457 | * | ||
458 | * Intel recommends to set DFR, LdR and TPR before enabling | ||
459 | * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel | ||
460 | * document number 292116). So here it goes... | ||
461 | */ | ||
462 | static void es7000_init_apic_ldr_cluster(void) | ||
463 | { | ||
464 | unsigned long val; | ||
465 | int cpu = smp_processor_id(); | ||
466 | |||
467 | apic_write(APIC_DFR, APIC_DFR_CLUSTER); | ||
468 | val = calculate_ldr(cpu); | ||
469 | apic_write(APIC_LDR, val); | ||
470 | } | ||
471 | |||
472 | static void es7000_init_apic_ldr(void) | ||
473 | { | ||
474 | unsigned long val; | ||
475 | int cpu = smp_processor_id(); | ||
476 | |||
477 | apic_write(APIC_DFR, APIC_DFR_FLAT); | ||
478 | val = calculate_ldr(cpu); | ||
479 | apic_write(APIC_LDR, val); | ||
480 | } | ||
481 | |||
482 | static void es7000_setup_apic_routing(void) | ||
483 | { | ||
484 | int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id()); | ||
485 | |||
486 | pr_info("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n", | ||
487 | (apic_version[apic] == 0x14) ? | ||
488 | "Physical Cluster" : "Logical Cluster", | ||
489 | nr_ioapics, cpumask_bits(es7000_target_cpus())[0]); | ||
490 | } | ||
491 | |||
492 | static int es7000_cpu_present_to_apicid(int mps_cpu) | ||
493 | { | ||
494 | if (!mps_cpu) | ||
495 | return boot_cpu_physical_apicid; | ||
496 | else if (mps_cpu < nr_cpu_ids) | ||
497 | return per_cpu(x86_bios_cpu_apicid, mps_cpu); | ||
498 | else | ||
499 | return BAD_APICID; | ||
500 | } | ||
501 | |||
502 | static int cpu_id; | ||
503 | |||
504 | static void es7000_apicid_to_cpu_present(int phys_apicid, physid_mask_t *retmap) | ||
505 | { | ||
506 | physid_set_mask_of_physid(cpu_id, retmap); | ||
507 | ++cpu_id; | ||
508 | } | ||
509 | |||
510 | static void es7000_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap) | ||
511 | { | ||
512 | /* For clustered we don't have a good way to do this yet - hack */ | ||
513 | physids_promote(0xFFL, retmap); | ||
514 | } | ||
515 | |||
516 | static int es7000_check_phys_apicid_present(int cpu_physical_apicid) | ||
517 | { | ||
518 | boot_cpu_physical_apicid = read_apic_id(); | ||
519 | return 1; | ||
520 | } | ||
521 | |||
522 | static inline int | ||
523 | es7000_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) | ||
524 | { | ||
525 | unsigned int round = 0; | ||
526 | unsigned int cpu, uninitialized_var(apicid); | ||
527 | |||
528 | /* | ||
529 | * The cpus in the mask must all be on the apic cluster. | ||
530 | */ | ||
531 | for_each_cpu_and(cpu, cpumask, cpu_online_mask) { | ||
532 | int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu); | ||
533 | |||
534 | if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { | ||
535 | WARN(1, "Not a valid mask!"); | ||
536 | |||
537 | return -EINVAL; | ||
538 | } | ||
539 | apicid |= new_apicid; | ||
540 | round++; | ||
541 | } | ||
542 | if (!round) | ||
543 | return -EINVAL; | ||
544 | *dest_id = apicid; | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | static int | ||
549 | es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask, | ||
550 | const struct cpumask *andmask, | ||
551 | unsigned int *apicid) | ||
552 | { | ||
553 | cpumask_var_t cpumask; | ||
554 | *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); | ||
555 | |||
556 | if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) | ||
557 | return 0; | ||
558 | |||
559 | cpumask_and(cpumask, inmask, andmask); | ||
560 | es7000_cpu_mask_to_apicid(cpumask, apicid); | ||
561 | |||
562 | free_cpumask_var(cpumask); | ||
563 | |||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | static int es7000_phys_pkg_id(int cpuid_apic, int index_msb) | ||
568 | { | ||
569 | return cpuid_apic >> index_msb; | ||
570 | } | ||
571 | |||
572 | static int probe_es7000(void) | ||
573 | { | ||
574 | /* probed later in mptable/ACPI hooks */ | ||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | static int es7000_mps_ret; | ||
579 | static int es7000_mps_oem_check(struct mpc_table *mpc, char *oem, | ||
580 | char *productid) | ||
581 | { | ||
582 | int ret = 0; | ||
583 | |||
584 | if (mpc->oemptr) { | ||
585 | struct mpc_oemtable *oem_table = | ||
586 | (struct mpc_oemtable *)mpc->oemptr; | ||
587 | |||
588 | if (!strncmp(oem, "UNISYS", 6)) | ||
589 | ret = parse_unisys_oem((char *)oem_table); | ||
590 | } | ||
591 | |||
592 | es7000_mps_ret = ret; | ||
593 | |||
594 | return ret && !es7000_apic_is_cluster(); | ||
595 | } | ||
596 | |||
597 | static int es7000_mps_oem_check_cluster(struct mpc_table *mpc, char *oem, | ||
598 | char *productid) | ||
599 | { | ||
600 | int ret = es7000_mps_ret; | ||
601 | |||
602 | return ret && es7000_apic_is_cluster(); | ||
603 | } | ||
604 | |||
605 | /* We've been warned by a false positive warning.Use __refdata to keep calm. */ | ||
606 | static struct apic __refdata apic_es7000_cluster = { | ||
607 | |||
608 | .name = "es7000", | ||
609 | .probe = probe_es7000, | ||
610 | .acpi_madt_oem_check = es7000_acpi_madt_oem_check_cluster, | ||
611 | .apic_id_valid = default_apic_id_valid, | ||
612 | .apic_id_registered = es7000_apic_id_registered, | ||
613 | |||
614 | .irq_delivery_mode = dest_LowestPrio, | ||
615 | /* logical delivery broadcast to all procs: */ | ||
616 | .irq_dest_mode = 1, | ||
617 | |||
618 | .target_cpus = target_cpus_cluster, | ||
619 | .disable_esr = 1, | ||
620 | .dest_logical = 0, | ||
621 | .check_apicid_used = es7000_check_apicid_used, | ||
622 | .check_apicid_present = es7000_check_apicid_present, | ||
623 | |||
624 | .vector_allocation_domain = flat_vector_allocation_domain, | ||
625 | .init_apic_ldr = es7000_init_apic_ldr_cluster, | ||
626 | |||
627 | .ioapic_phys_id_map = es7000_ioapic_phys_id_map, | ||
628 | .setup_apic_routing = es7000_setup_apic_routing, | ||
629 | .multi_timer_check = NULL, | ||
630 | .cpu_present_to_apicid = es7000_cpu_present_to_apicid, | ||
631 | .apicid_to_cpu_present = es7000_apicid_to_cpu_present, | ||
632 | .setup_portio_remap = NULL, | ||
633 | .check_phys_apicid_present = es7000_check_phys_apicid_present, | ||
634 | .enable_apic_mode = es7000_enable_apic_mode, | ||
635 | .phys_pkg_id = es7000_phys_pkg_id, | ||
636 | .mps_oem_check = es7000_mps_oem_check_cluster, | ||
637 | |||
638 | .get_apic_id = es7000_get_apic_id, | ||
639 | .set_apic_id = NULL, | ||
640 | .apic_id_mask = 0xFF << 24, | ||
641 | |||
642 | .cpu_mask_to_apicid_and = es7000_cpu_mask_to_apicid_and, | ||
643 | |||
644 | .send_IPI_mask = es7000_send_IPI_mask, | ||
645 | .send_IPI_mask_allbutself = NULL, | ||
646 | .send_IPI_allbutself = es7000_send_IPI_allbutself, | ||
647 | .send_IPI_all = es7000_send_IPI_all, | ||
648 | .send_IPI_self = default_send_IPI_self, | ||
649 | |||
650 | .wakeup_secondary_cpu = wakeup_secondary_cpu_via_mip, | ||
651 | |||
652 | .trampoline_phys_low = 0x467, | ||
653 | .trampoline_phys_high = 0x469, | ||
654 | |||
655 | .wait_for_init_deassert = false, | ||
656 | /* Nothing to do for most platforms, since cleared by the INIT cycle: */ | ||
657 | .smp_callin_clear_local_apic = NULL, | ||
658 | .inquire_remote_apic = default_inquire_remote_apic, | ||
659 | |||
660 | .read = native_apic_mem_read, | ||
661 | .write = native_apic_mem_write, | ||
662 | .eoi_write = native_apic_mem_write, | ||
663 | .icr_read = native_apic_icr_read, | ||
664 | .icr_write = native_apic_icr_write, | ||
665 | .wait_icr_idle = native_apic_wait_icr_idle, | ||
666 | .safe_wait_icr_idle = native_safe_apic_wait_icr_idle, | ||
667 | |||
668 | .x86_32_early_logical_apicid = es7000_early_logical_apicid, | ||
669 | }; | ||
670 | |||
671 | static struct apic __refdata apic_es7000 = { | ||
672 | |||
673 | .name = "es7000", | ||
674 | .probe = probe_es7000, | ||
675 | .acpi_madt_oem_check = es7000_acpi_madt_oem_check, | ||
676 | .apic_id_valid = default_apic_id_valid, | ||
677 | .apic_id_registered = es7000_apic_id_registered, | ||
678 | |||
679 | .irq_delivery_mode = dest_Fixed, | ||
680 | /* phys delivery to target CPUs: */ | ||
681 | .irq_dest_mode = 0, | ||
682 | |||
683 | .target_cpus = es7000_target_cpus, | ||
684 | .disable_esr = 1, | ||
685 | .dest_logical = 0, | ||
686 | .check_apicid_used = es7000_check_apicid_used, | ||
687 | .check_apicid_present = es7000_check_apicid_present, | ||
688 | |||
689 | .vector_allocation_domain = flat_vector_allocation_domain, | ||
690 | .init_apic_ldr = es7000_init_apic_ldr, | ||
691 | |||
692 | .ioapic_phys_id_map = es7000_ioapic_phys_id_map, | ||
693 | .setup_apic_routing = es7000_setup_apic_routing, | ||
694 | .multi_timer_check = NULL, | ||
695 | .cpu_present_to_apicid = es7000_cpu_present_to_apicid, | ||
696 | .apicid_to_cpu_present = es7000_apicid_to_cpu_present, | ||
697 | .setup_portio_remap = NULL, | ||
698 | .check_phys_apicid_present = es7000_check_phys_apicid_present, | ||
699 | .enable_apic_mode = es7000_enable_apic_mode, | ||
700 | .phys_pkg_id = es7000_phys_pkg_id, | ||
701 | .mps_oem_check = es7000_mps_oem_check, | ||
702 | |||
703 | .get_apic_id = es7000_get_apic_id, | ||
704 | .set_apic_id = NULL, | ||
705 | .apic_id_mask = 0xFF << 24, | ||
706 | |||
707 | .cpu_mask_to_apicid_and = es7000_cpu_mask_to_apicid_and, | ||
708 | |||
709 | .send_IPI_mask = es7000_send_IPI_mask, | ||
710 | .send_IPI_mask_allbutself = NULL, | ||
711 | .send_IPI_allbutself = es7000_send_IPI_allbutself, | ||
712 | .send_IPI_all = es7000_send_IPI_all, | ||
713 | .send_IPI_self = default_send_IPI_self, | ||
714 | |||
715 | .trampoline_phys_low = 0x467, | ||
716 | .trampoline_phys_high = 0x469, | ||
717 | |||
718 | .wait_for_init_deassert = true, | ||
719 | /* Nothing to do for most platforms, since cleared by the INIT cycle: */ | ||
720 | .smp_callin_clear_local_apic = NULL, | ||
721 | .inquire_remote_apic = default_inquire_remote_apic, | ||
722 | |||
723 | .read = native_apic_mem_read, | ||
724 | .write = native_apic_mem_write, | ||
725 | .eoi_write = native_apic_mem_write, | ||
726 | .icr_read = native_apic_icr_read, | ||
727 | .icr_write = native_apic_icr_write, | ||
728 | .wait_icr_idle = native_apic_wait_icr_idle, | ||
729 | .safe_wait_icr_idle = native_safe_apic_wait_icr_idle, | ||
730 | |||
731 | .x86_32_early_logical_apicid = es7000_early_logical_apicid, | ||
732 | }; | ||
733 | |||
734 | /* | ||
735 | * Need to check for es7000 followed by es7000_cluster, so this order | ||
736 | * in apic_drivers is important. | ||
737 | */ | ||
738 | apic_drivers(apic_es7000, apic_es7000_cluster); | ||