diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 12 | ||||
-rw-r--r-- | arch/x86/kernel/apic/Makefile | 3 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/apic/es7000_32.c | 738 | ||||
-rw-r--r-- | arch/x86/kernel/apic/numaq_32.c | 524 | ||||
-rw-r--r-- | arch/x86/kernel/apic/summit_32.c | 550 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/intel.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 1 |
8 files changed, 0 insertions, 1833 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 8e61d23b8f64..86281ffb96d6 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -903,10 +903,6 @@ static int __init acpi_parse_madt_lapic_entries(void) | |||
903 | #ifdef CONFIG_X86_IO_APIC | 903 | #ifdef CONFIG_X86_IO_APIC |
904 | #define MP_ISA_BUS 0 | 904 | #define MP_ISA_BUS 0 |
905 | 905 | ||
906 | #ifdef CONFIG_X86_ES7000 | ||
907 | extern int es7000_plat; | ||
908 | #endif | ||
909 | |||
910 | void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) | 906 | void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) |
911 | { | 907 | { |
912 | int ioapic; | 908 | int ioapic; |
@@ -956,14 +952,6 @@ void __init mp_config_acpi_legacy_irqs(void) | |||
956 | set_bit(MP_ISA_BUS, mp_bus_not_pci); | 952 | set_bit(MP_ISA_BUS, mp_bus_not_pci); |
957 | pr_debug("Bus #%d is ISA\n", MP_ISA_BUS); | 953 | pr_debug("Bus #%d is ISA\n", MP_ISA_BUS); |
958 | 954 | ||
959 | #ifdef CONFIG_X86_ES7000 | ||
960 | /* | ||
961 | * Older generations of ES7000 have no legacy identity mappings | ||
962 | */ | ||
963 | if (es7000_plat == 1) | ||
964 | return; | ||
965 | #endif | ||
966 | |||
967 | /* | 955 | /* |
968 | * Use the default configuration for the IRQs 0-15. Unless | 956 | * Use the default configuration for the IRQs 0-15. Unless |
969 | * overridden by (MADT) interrupt source override entries. | 957 | * overridden by (MADT) interrupt source override entries. |
diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile index 0ae0323b1f9c..dcb5b15401ce 100644 --- a/arch/x86/kernel/apic/Makefile +++ b/arch/x86/kernel/apic/Makefile | |||
@@ -18,10 +18,7 @@ obj-y += apic_flat_64.o | |||
18 | endif | 18 | endif |
19 | 19 | ||
20 | # APIC probe will depend on the listing order here | 20 | # APIC probe will depend on the listing order here |
21 | obj-$(CONFIG_X86_NUMAQ) += numaq_32.o | ||
22 | obj-$(CONFIG_X86_SUMMIT) += summit_32.o | ||
23 | obj-$(CONFIG_X86_BIGSMP) += bigsmp_32.o | 21 | obj-$(CONFIG_X86_BIGSMP) += bigsmp_32.o |
24 | obj-$(CONFIG_X86_ES7000) += es7000_32.o | ||
25 | 22 | ||
26 | # For 32bit, probe_32 need to be listed last | 23 | # For 32bit, probe_32 need to be listed last |
27 | obj-$(CONFIG_X86_LOCAL_APIC) += probe_$(BITS).o | 24 | obj-$(CONFIG_X86_LOCAL_APIC) += probe_$(BITS).o |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 53e20531470e..481ae38f6a44 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -2136,7 +2136,6 @@ int generic_processor_info(int apicid, int version) | |||
2136 | * | 2136 | * |
2137 | * - arch/x86/kernel/mpparse.c: MP_processor_info() | 2137 | * - arch/x86/kernel/mpparse.c: MP_processor_info() |
2138 | * - arch/x86/mm/amdtopology.c: amd_numa_init() | 2138 | * - arch/x86/mm/amdtopology.c: amd_numa_init() |
2139 | * - arch/x86/platform/visws/visws_quirks.c: MP_processor_info() | ||
2140 | * | 2139 | * |
2141 | * This function is executed with the modified | 2140 | * This function is executed with the modified |
2142 | * boot_cpu_physical_apicid. So, disabled_cpu_apicid kernel | 2141 | * boot_cpu_physical_apicid. So, disabled_cpu_apicid kernel |
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); | ||
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c deleted file mode 100644 index 030ea1c04f72..000000000000 --- a/arch/x86/kernel/apic/numaq_32.c +++ /dev/null | |||
@@ -1,524 +0,0 @@ | |||
1 | /* | ||
2 | * Written by: Patricia Gaughen, IBM Corporation | ||
3 | * | ||
4 | * Copyright (C) 2002, IBM Corp. | ||
5 | * Copyright (C) 2009, Red Hat, Inc., Ingo Molnar | ||
6 | * | ||
7 | * All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
17 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
18 | * details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | * Send feedback to <gone@us.ibm.com> | ||
25 | */ | ||
26 | #include <linux/nodemask.h> | ||
27 | #include <linux/topology.h> | ||
28 | #include <linux/bootmem.h> | ||
29 | #include <linux/memblock.h> | ||
30 | #include <linux/threads.h> | ||
31 | #include <linux/cpumask.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/mmzone.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/string.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/numa.h> | ||
38 | #include <linux/smp.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/mm.h> | ||
41 | |||
42 | #include <asm/processor.h> | ||
43 | #include <asm/fixmap.h> | ||
44 | #include <asm/mpspec.h> | ||
45 | #include <asm/numaq.h> | ||
46 | #include <asm/setup.h> | ||
47 | #include <asm/apic.h> | ||
48 | #include <asm/e820.h> | ||
49 | #include <asm/ipi.h> | ||
50 | |||
51 | int found_numaq; | ||
52 | |||
53 | /* | ||
54 | * Have to match translation table entries to main table entries by counter | ||
55 | * hence the mpc_record variable .... can't see a less disgusting way of | ||
56 | * doing this .... | ||
57 | */ | ||
58 | struct mpc_trans { | ||
59 | unsigned char mpc_type; | ||
60 | unsigned char trans_len; | ||
61 | unsigned char trans_type; | ||
62 | unsigned char trans_quad; | ||
63 | unsigned char trans_global; | ||
64 | unsigned char trans_local; | ||
65 | unsigned short trans_reserved; | ||
66 | }; | ||
67 | |||
68 | static int mpc_record; | ||
69 | |||
70 | static struct mpc_trans *translation_table[MAX_MPC_ENTRY]; | ||
71 | |||
72 | int mp_bus_id_to_node[MAX_MP_BUSSES]; | ||
73 | int mp_bus_id_to_local[MAX_MP_BUSSES]; | ||
74 | int quad_local_to_mp_bus_id[NR_CPUS/4][4]; | ||
75 | |||
76 | |||
77 | static inline void numaq_register_node(int node, struct sys_cfg_data *scd) | ||
78 | { | ||
79 | struct eachquadmem *eq = scd->eq + node; | ||
80 | u64 start = (u64)(eq->hi_shrd_mem_start - eq->priv_mem_size) << 20; | ||
81 | u64 end = (u64)(eq->hi_shrd_mem_start + eq->hi_shrd_mem_size) << 20; | ||
82 | int ret; | ||
83 | |||
84 | node_set(node, numa_nodes_parsed); | ||
85 | ret = numa_add_memblk(node, start, end); | ||
86 | BUG_ON(ret < 0); | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * Function: smp_dump_qct() | ||
91 | * | ||
92 | * Description: gets memory layout from the quad config table. This | ||
93 | * function also updates numa_nodes_parsed with the nodes (quads) present. | ||
94 | */ | ||
95 | static void __init smp_dump_qct(void) | ||
96 | { | ||
97 | struct sys_cfg_data *scd; | ||
98 | int node; | ||
99 | |||
100 | scd = (void *)__va(SYS_CFG_DATA_PRIV_ADDR); | ||
101 | |||
102 | for_each_node(node) { | ||
103 | if (scd->quads_present31_0 & (1 << node)) | ||
104 | numaq_register_node(node, scd); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | void numaq_tsc_disable(void) | ||
109 | { | ||
110 | if (!found_numaq) | ||
111 | return; | ||
112 | |||
113 | if (num_online_nodes() > 1) { | ||
114 | printk(KERN_DEBUG "NUMAQ: disabling TSC\n"); | ||
115 | setup_clear_cpu_cap(X86_FEATURE_TSC); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | static void __init numaq_tsc_init(void) | ||
120 | { | ||
121 | numaq_tsc_disable(); | ||
122 | } | ||
123 | |||
124 | static inline int generate_logical_apicid(int quad, int phys_apicid) | ||
125 | { | ||
126 | return (quad << 4) + (phys_apicid ? phys_apicid << 1 : 1); | ||
127 | } | ||
128 | |||
129 | /* x86_quirks member */ | ||
130 | static int mpc_apic_id(struct mpc_cpu *m) | ||
131 | { | ||
132 | int quad = translation_table[mpc_record]->trans_quad; | ||
133 | int logical_apicid = generate_logical_apicid(quad, m->apicid); | ||
134 | |||
135 | printk(KERN_DEBUG | ||
136 | "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n", | ||
137 | m->apicid, (m->cpufeature & CPU_FAMILY_MASK) >> 8, | ||
138 | (m->cpufeature & CPU_MODEL_MASK) >> 4, | ||
139 | m->apicver, quad, logical_apicid); | ||
140 | |||
141 | return logical_apicid; | ||
142 | } | ||
143 | |||
144 | /* x86_quirks member */ | ||
145 | static void mpc_oem_bus_info(struct mpc_bus *m, char *name) | ||
146 | { | ||
147 | int quad = translation_table[mpc_record]->trans_quad; | ||
148 | int local = translation_table[mpc_record]->trans_local; | ||
149 | |||
150 | mp_bus_id_to_node[m->busid] = quad; | ||
151 | mp_bus_id_to_local[m->busid] = local; | ||
152 | |||
153 | printk(KERN_INFO "Bus #%d is %s (node %d)\n", m->busid, name, quad); | ||
154 | } | ||
155 | |||
156 | /* x86_quirks member */ | ||
157 | static void mpc_oem_pci_bus(struct mpc_bus *m) | ||
158 | { | ||
159 | int quad = translation_table[mpc_record]->trans_quad; | ||
160 | int local = translation_table[mpc_record]->trans_local; | ||
161 | |||
162 | quad_local_to_mp_bus_id[quad][local] = m->busid; | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Called from mpparse code. | ||
167 | * mode = 0: prescan | ||
168 | * mode = 1: one mpc entry scanned | ||
169 | */ | ||
170 | static void numaq_mpc_record(unsigned int mode) | ||
171 | { | ||
172 | if (!mode) | ||
173 | mpc_record = 0; | ||
174 | else | ||
175 | mpc_record++; | ||
176 | } | ||
177 | |||
178 | static void __init MP_translation_info(struct mpc_trans *m) | ||
179 | { | ||
180 | printk(KERN_INFO | ||
181 | "Translation: record %d, type %d, quad %d, global %d, local %d\n", | ||
182 | mpc_record, m->trans_type, m->trans_quad, m->trans_global, | ||
183 | m->trans_local); | ||
184 | |||
185 | if (mpc_record >= MAX_MPC_ENTRY) | ||
186 | printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n"); | ||
187 | else | ||
188 | translation_table[mpc_record] = m; /* stash this for later */ | ||
189 | |||
190 | if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad)) | ||
191 | node_set_online(m->trans_quad); | ||
192 | } | ||
193 | |||
194 | static int __init mpf_checksum(unsigned char *mp, int len) | ||
195 | { | ||
196 | int sum = 0; | ||
197 | |||
198 | while (len--) | ||
199 | sum += *mp++; | ||
200 | |||
201 | return sum & 0xFF; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * Read/parse the MPC oem tables | ||
206 | */ | ||
207 | static void __init smp_read_mpc_oem(struct mpc_table *mpc) | ||
208 | { | ||
209 | struct mpc_oemtable *oemtable = (void *)(long)mpc->oemptr; | ||
210 | int count = sizeof(*oemtable); /* the header size */ | ||
211 | unsigned char *oemptr = ((unsigned char *)oemtable) + count; | ||
212 | |||
213 | mpc_record = 0; | ||
214 | printk(KERN_INFO | ||
215 | "Found an OEM MPC table at %8p - parsing it...\n", oemtable); | ||
216 | |||
217 | if (memcmp(oemtable->signature, MPC_OEM_SIGNATURE, 4)) { | ||
218 | printk(KERN_WARNING | ||
219 | "SMP mpc oemtable: bad signature [%c%c%c%c]!\n", | ||
220 | oemtable->signature[0], oemtable->signature[1], | ||
221 | oemtable->signature[2], oemtable->signature[3]); | ||
222 | return; | ||
223 | } | ||
224 | |||
225 | if (mpf_checksum((unsigned char *)oemtable, oemtable->length)) { | ||
226 | printk(KERN_WARNING "SMP oem mptable: checksum error!\n"); | ||
227 | return; | ||
228 | } | ||
229 | |||
230 | while (count < oemtable->length) { | ||
231 | switch (*oemptr) { | ||
232 | case MP_TRANSLATION: | ||
233 | { | ||
234 | struct mpc_trans *m = (void *)oemptr; | ||
235 | |||
236 | MP_translation_info(m); | ||
237 | oemptr += sizeof(*m); | ||
238 | count += sizeof(*m); | ||
239 | ++mpc_record; | ||
240 | break; | ||
241 | } | ||
242 | default: | ||
243 | printk(KERN_WARNING | ||
244 | "Unrecognised OEM table entry type! - %d\n", | ||
245 | (int)*oemptr); | ||
246 | return; | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | |||
251 | static __init void early_check_numaq(void) | ||
252 | { | ||
253 | /* | ||
254 | * get boot-time SMP configuration: | ||
255 | */ | ||
256 | if (smp_found_config) | ||
257 | early_get_smp_config(); | ||
258 | |||
259 | if (found_numaq) { | ||
260 | x86_init.mpparse.mpc_record = numaq_mpc_record; | ||
261 | x86_init.mpparse.setup_ioapic_ids = x86_init_noop; | ||
262 | x86_init.mpparse.mpc_apic_id = mpc_apic_id; | ||
263 | x86_init.mpparse.smp_read_mpc_oem = smp_read_mpc_oem; | ||
264 | x86_init.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus; | ||
265 | x86_init.mpparse.mpc_oem_bus_info = mpc_oem_bus_info; | ||
266 | x86_init.timers.tsc_pre_init = numaq_tsc_init; | ||
267 | x86_init.pci.init = pci_numaq_init; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | int __init numaq_numa_init(void) | ||
272 | { | ||
273 | early_check_numaq(); | ||
274 | if (!found_numaq) | ||
275 | return -ENOENT; | ||
276 | smp_dump_qct(); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | #define NUMAQ_APIC_DFR_VALUE (APIC_DFR_CLUSTER) | ||
282 | |||
283 | static inline unsigned int numaq_get_apic_id(unsigned long x) | ||
284 | { | ||
285 | return (x >> 24) & 0x0F; | ||
286 | } | ||
287 | |||
288 | static inline void numaq_send_IPI_mask(const struct cpumask *mask, int vector) | ||
289 | { | ||
290 | default_send_IPI_mask_sequence_logical(mask, vector); | ||
291 | } | ||
292 | |||
293 | static inline void numaq_send_IPI_allbutself(int vector) | ||
294 | { | ||
295 | default_send_IPI_mask_allbutself_logical(cpu_online_mask, vector); | ||
296 | } | ||
297 | |||
298 | static inline void numaq_send_IPI_all(int vector) | ||
299 | { | ||
300 | numaq_send_IPI_mask(cpu_online_mask, vector); | ||
301 | } | ||
302 | |||
303 | #define NUMAQ_TRAMPOLINE_PHYS_LOW (0x8) | ||
304 | #define NUMAQ_TRAMPOLINE_PHYS_HIGH (0xa) | ||
305 | |||
306 | /* | ||
307 | * Because we use NMIs rather than the INIT-STARTUP sequence to | ||
308 | * bootstrap the CPUs, the APIC may be in a weird state. Kick it: | ||
309 | */ | ||
310 | static inline void numaq_smp_callin_clear_local_apic(void) | ||
311 | { | ||
312 | clear_local_APIC(); | ||
313 | } | ||
314 | |||
315 | static inline const struct cpumask *numaq_target_cpus(void) | ||
316 | { | ||
317 | return cpu_all_mask; | ||
318 | } | ||
319 | |||
320 | static unsigned long numaq_check_apicid_used(physid_mask_t *map, int apicid) | ||
321 | { | ||
322 | return physid_isset(apicid, *map); | ||
323 | } | ||
324 | |||
325 | static inline unsigned long numaq_check_apicid_present(int bit) | ||
326 | { | ||
327 | return physid_isset(bit, phys_cpu_present_map); | ||
328 | } | ||
329 | |||
330 | static inline int numaq_apic_id_registered(void) | ||
331 | { | ||
332 | return 1; | ||
333 | } | ||
334 | |||
335 | static inline void numaq_init_apic_ldr(void) | ||
336 | { | ||
337 | /* Already done in NUMA-Q firmware */ | ||
338 | } | ||
339 | |||
340 | static inline void numaq_setup_apic_routing(void) | ||
341 | { | ||
342 | printk(KERN_INFO | ||
343 | "Enabling APIC mode: NUMA-Q. Using %d I/O APICs\n", | ||
344 | nr_ioapics); | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | * Skip adding the timer int on secondary nodes, which causes | ||
349 | * a small but painful rift in the time-space continuum. | ||
350 | */ | ||
351 | static inline int numaq_multi_timer_check(int apic, int irq) | ||
352 | { | ||
353 | return apic != 0 && irq == 0; | ||
354 | } | ||
355 | |||
356 | static inline void numaq_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap) | ||
357 | { | ||
358 | /* We don't have a good way to do this yet - hack */ | ||
359 | return physids_promote(0xFUL, retmap); | ||
360 | } | ||
361 | |||
362 | /* | ||
363 | * Supporting over 60 cpus on NUMA-Q requires a locality-dependent | ||
364 | * cpu to APIC ID relation to properly interact with the intelligent | ||
365 | * mode of the cluster controller. | ||
366 | */ | ||
367 | static inline int numaq_cpu_present_to_apicid(int mps_cpu) | ||
368 | { | ||
369 | if (mps_cpu < 60) | ||
370 | return ((mps_cpu >> 2) << 4) | (1 << (mps_cpu & 0x3)); | ||
371 | else | ||
372 | return BAD_APICID; | ||
373 | } | ||
374 | |||
375 | static inline int numaq_apicid_to_node(int logical_apicid) | ||
376 | { | ||
377 | return logical_apicid >> 4; | ||
378 | } | ||
379 | |||
380 | static int numaq_numa_cpu_node(int cpu) | ||
381 | { | ||
382 | int logical_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu); | ||
383 | |||
384 | if (logical_apicid != BAD_APICID) | ||
385 | return numaq_apicid_to_node(logical_apicid); | ||
386 | return NUMA_NO_NODE; | ||
387 | } | ||
388 | |||
389 | static void numaq_apicid_to_cpu_present(int logical_apicid, physid_mask_t *retmap) | ||
390 | { | ||
391 | int node = numaq_apicid_to_node(logical_apicid); | ||
392 | int cpu = __ffs(logical_apicid & 0xf); | ||
393 | |||
394 | physid_set_mask_of_physid(cpu + 4*node, retmap); | ||
395 | } | ||
396 | |||
397 | /* Where the IO area was mapped on multiquad, always 0 otherwise */ | ||
398 | void *xquad_portio; | ||
399 | |||
400 | static inline int numaq_check_phys_apicid_present(int phys_apicid) | ||
401 | { | ||
402 | return 1; | ||
403 | } | ||
404 | |||
405 | /* | ||
406 | * We use physical apicids here, not logical, so just return the default | ||
407 | * physical broadcast to stop people from breaking us | ||
408 | */ | ||
409 | static int | ||
410 | numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | ||
411 | const struct cpumask *andmask, | ||
412 | unsigned int *apicid) | ||
413 | { | ||
414 | *apicid = 0x0F; | ||
415 | return 0; | ||
416 | } | ||
417 | |||
418 | /* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */ | ||
419 | static inline int numaq_phys_pkg_id(int cpuid_apic, int index_msb) | ||
420 | { | ||
421 | return cpuid_apic >> index_msb; | ||
422 | } | ||
423 | |||
424 | static int | ||
425 | numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) | ||
426 | { | ||
427 | if (strncmp(oem, "IBM NUMA", 8)) | ||
428 | printk(KERN_ERR "Warning! Not a NUMA-Q system!\n"); | ||
429 | else | ||
430 | found_numaq = 1; | ||
431 | |||
432 | return found_numaq; | ||
433 | } | ||
434 | |||
435 | static int probe_numaq(void) | ||
436 | { | ||
437 | /* already know from get_memcfg_numaq() */ | ||
438 | return found_numaq; | ||
439 | } | ||
440 | |||
441 | static void numaq_setup_portio_remap(void) | ||
442 | { | ||
443 | int num_quads = num_online_nodes(); | ||
444 | |||
445 | if (num_quads <= 1) | ||
446 | return; | ||
447 | |||
448 | printk(KERN_INFO | ||
449 | "Remapping cross-quad port I/O for %d quads\n", num_quads); | ||
450 | |||
451 | xquad_portio = ioremap(XQUAD_PORTIO_BASE, num_quads*XQUAD_PORTIO_QUAD); | ||
452 | |||
453 | printk(KERN_INFO | ||
454 | "xquad_portio vaddr 0x%08lx, len %08lx\n", | ||
455 | (u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD); | ||
456 | } | ||
457 | |||
458 | /* Use __refdata to keep false positive warning calm. */ | ||
459 | static struct apic __refdata apic_numaq = { | ||
460 | |||
461 | .name = "NUMAQ", | ||
462 | .probe = probe_numaq, | ||
463 | .acpi_madt_oem_check = NULL, | ||
464 | .apic_id_valid = default_apic_id_valid, | ||
465 | .apic_id_registered = numaq_apic_id_registered, | ||
466 | |||
467 | .irq_delivery_mode = dest_LowestPrio, | ||
468 | /* physical delivery on LOCAL quad: */ | ||
469 | .irq_dest_mode = 0, | ||
470 | |||
471 | .target_cpus = numaq_target_cpus, | ||
472 | .disable_esr = 1, | ||
473 | .dest_logical = APIC_DEST_LOGICAL, | ||
474 | .check_apicid_used = numaq_check_apicid_used, | ||
475 | .check_apicid_present = numaq_check_apicid_present, | ||
476 | |||
477 | .vector_allocation_domain = flat_vector_allocation_domain, | ||
478 | .init_apic_ldr = numaq_init_apic_ldr, | ||
479 | |||
480 | .ioapic_phys_id_map = numaq_ioapic_phys_id_map, | ||
481 | .setup_apic_routing = numaq_setup_apic_routing, | ||
482 | .multi_timer_check = numaq_multi_timer_check, | ||
483 | .cpu_present_to_apicid = numaq_cpu_present_to_apicid, | ||
484 | .apicid_to_cpu_present = numaq_apicid_to_cpu_present, | ||
485 | .setup_portio_remap = numaq_setup_portio_remap, | ||
486 | .check_phys_apicid_present = numaq_check_phys_apicid_present, | ||
487 | .enable_apic_mode = NULL, | ||
488 | .phys_pkg_id = numaq_phys_pkg_id, | ||
489 | .mps_oem_check = numaq_mps_oem_check, | ||
490 | |||
491 | .get_apic_id = numaq_get_apic_id, | ||
492 | .set_apic_id = NULL, | ||
493 | .apic_id_mask = 0x0F << 24, | ||
494 | |||
495 | .cpu_mask_to_apicid_and = numaq_cpu_mask_to_apicid_and, | ||
496 | |||
497 | .send_IPI_mask = numaq_send_IPI_mask, | ||
498 | .send_IPI_mask_allbutself = NULL, | ||
499 | .send_IPI_allbutself = numaq_send_IPI_allbutself, | ||
500 | .send_IPI_all = numaq_send_IPI_all, | ||
501 | .send_IPI_self = default_send_IPI_self, | ||
502 | |||
503 | .wakeup_secondary_cpu = wakeup_secondary_cpu_via_nmi, | ||
504 | .trampoline_phys_low = NUMAQ_TRAMPOLINE_PHYS_LOW, | ||
505 | .trampoline_phys_high = NUMAQ_TRAMPOLINE_PHYS_HIGH, | ||
506 | |||
507 | /* We don't do anything here because we use NMI's to boot instead */ | ||
508 | .wait_for_init_deassert = false, | ||
509 | .smp_callin_clear_local_apic = numaq_smp_callin_clear_local_apic, | ||
510 | .inquire_remote_apic = NULL, | ||
511 | |||
512 | .read = native_apic_mem_read, | ||
513 | .write = native_apic_mem_write, | ||
514 | .eoi_write = native_apic_mem_write, | ||
515 | .icr_read = native_apic_icr_read, | ||
516 | .icr_write = native_apic_icr_write, | ||
517 | .wait_icr_idle = native_apic_wait_icr_idle, | ||
518 | .safe_wait_icr_idle = native_safe_apic_wait_icr_idle, | ||
519 | |||
520 | .x86_32_early_logical_apicid = noop_x86_32_early_logical_apicid, | ||
521 | .x86_32_numa_cpu_node = numaq_numa_cpu_node, | ||
522 | }; | ||
523 | |||
524 | apic_driver(apic_numaq); | ||
diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c deleted file mode 100644 index b656128611cd..000000000000 --- a/arch/x86/kernel/apic/summit_32.c +++ /dev/null | |||
@@ -1,550 +0,0 @@ | |||
1 | /* | ||
2 | * IBM Summit-Specific Code | ||
3 | * | ||
4 | * Written By: Matthew Dobson, IBM Corporation | ||
5 | * | ||
6 | * Copyright (c) 2003 IBM Corp. | ||
7 | * | ||
8 | * All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or (at | ||
13 | * your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
18 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
19 | * details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | * Send feedback to <colpatch@us.ibm.com> | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #define pr_fmt(fmt) "summit: %s: " fmt, __func__ | ||
30 | |||
31 | #include <linux/mm.h> | ||
32 | #include <asm/io.h> | ||
33 | #include <asm/bios_ebda.h> | ||
34 | |||
35 | /* | ||
36 | * APIC driver for the IBM "Summit" chipset. | ||
37 | */ | ||
38 | #include <linux/threads.h> | ||
39 | #include <linux/cpumask.h> | ||
40 | #include <asm/mpspec.h> | ||
41 | #include <asm/apic.h> | ||
42 | #include <asm/smp.h> | ||
43 | #include <asm/fixmap.h> | ||
44 | #include <asm/apicdef.h> | ||
45 | #include <asm/ipi.h> | ||
46 | #include <linux/kernel.h> | ||
47 | #include <linux/string.h> | ||
48 | #include <linux/gfp.h> | ||
49 | #include <linux/smp.h> | ||
50 | |||
51 | static unsigned summit_get_apic_id(unsigned long x) | ||
52 | { | ||
53 | return (x >> 24) & 0xFF; | ||
54 | } | ||
55 | |||
56 | static inline void summit_send_IPI_mask(const struct cpumask *mask, int vector) | ||
57 | { | ||
58 | default_send_IPI_mask_sequence_logical(mask, vector); | ||
59 | } | ||
60 | |||
61 | static void summit_send_IPI_allbutself(int vector) | ||
62 | { | ||
63 | default_send_IPI_mask_allbutself_logical(cpu_online_mask, vector); | ||
64 | } | ||
65 | |||
66 | static void summit_send_IPI_all(int vector) | ||
67 | { | ||
68 | summit_send_IPI_mask(cpu_online_mask, vector); | ||
69 | } | ||
70 | |||
71 | #include <asm/tsc.h> | ||
72 | |||
73 | extern int use_cyclone; | ||
74 | |||
75 | #ifdef CONFIG_X86_SUMMIT_NUMA | ||
76 | static void setup_summit(void); | ||
77 | #else | ||
78 | static inline void setup_summit(void) {} | ||
79 | #endif | ||
80 | |||
81 | static int summit_mps_oem_check(struct mpc_table *mpc, char *oem, | ||
82 | char *productid) | ||
83 | { | ||
84 | if (!strncmp(oem, "IBM ENSW", 8) && | ||
85 | (!strncmp(productid, "VIGIL SMP", 9) | ||
86 | || !strncmp(productid, "EXA", 3) | ||
87 | || !strncmp(productid, "RUTHLESS SMP", 12))){ | ||
88 | mark_tsc_unstable("Summit based system"); | ||
89 | use_cyclone = 1; /*enable cyclone-timer*/ | ||
90 | setup_summit(); | ||
91 | return 1; | ||
92 | } | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | /* Hook from generic ACPI tables.c */ | ||
97 | static int summit_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | ||
98 | { | ||
99 | if (!strncmp(oem_id, "IBM", 3) && | ||
100 | (!strncmp(oem_table_id, "SERVIGIL", 8) | ||
101 | || !strncmp(oem_table_id, "EXA", 3))){ | ||
102 | mark_tsc_unstable("Summit based system"); | ||
103 | use_cyclone = 1; /*enable cyclone-timer*/ | ||
104 | setup_summit(); | ||
105 | return 1; | ||
106 | } | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | struct rio_table_hdr { | ||
111 | unsigned char version; /* Version number of this data structure */ | ||
112 | /* Version 3 adds chassis_num & WP_index */ | ||
113 | unsigned char num_scal_dev; /* # of Scalability devices (Twisters for Vigil) */ | ||
114 | unsigned char num_rio_dev; /* # of RIO I/O devices (Cyclones and Winnipegs) */ | ||
115 | } __attribute__((packed)); | ||
116 | |||
117 | struct scal_detail { | ||
118 | unsigned char node_id; /* Scalability Node ID */ | ||
119 | unsigned long CBAR; /* Address of 1MB register space */ | ||
120 | unsigned char port0node; /* Node ID port connected to: 0xFF=None */ | ||
121 | unsigned char port0port; /* Port num port connected to: 0,1,2, or 0xFF=None */ | ||
122 | unsigned char port1node; /* Node ID port connected to: 0xFF = None */ | ||
123 | unsigned char port1port; /* Port num port connected to: 0,1,2, or 0xFF=None */ | ||
124 | unsigned char port2node; /* Node ID port connected to: 0xFF = None */ | ||
125 | unsigned char port2port; /* Port num port connected to: 0,1,2, or 0xFF=None */ | ||
126 | unsigned char chassis_num; /* 1 based Chassis number (1 = boot node) */ | ||
127 | } __attribute__((packed)); | ||
128 | |||
129 | struct rio_detail { | ||
130 | unsigned char node_id; /* RIO Node ID */ | ||
131 | unsigned long BBAR; /* Address of 1MB register space */ | ||
132 | unsigned char type; /* Type of device */ | ||
133 | unsigned char owner_id; /* For WPEG: Node ID of Cyclone that owns this WPEG*/ | ||
134 | /* For CYC: Node ID of Twister that owns this CYC */ | ||
135 | unsigned char port0node; /* Node ID port connected to: 0xFF=None */ | ||
136 | unsigned char port0port; /* Port num port connected to: 0,1,2, or 0xFF=None */ | ||
137 | unsigned char port1node; /* Node ID port connected to: 0xFF=None */ | ||
138 | unsigned char port1port; /* Port num port connected to: 0,1,2, or 0xFF=None */ | ||
139 | unsigned char first_slot; /* For WPEG: Lowest slot number below this WPEG */ | ||
140 | /* For CYC: 0 */ | ||
141 | unsigned char status; /* For WPEG: Bit 0 = 1 : the XAPIC is used */ | ||
142 | /* = 0 : the XAPIC is not used, ie:*/ | ||
143 | /* ints fwded to another XAPIC */ | ||
144 | /* Bits1:7 Reserved */ | ||
145 | /* For CYC: Bits0:7 Reserved */ | ||
146 | unsigned char WP_index; /* For WPEG: WPEG instance index - lower ones have */ | ||
147 | /* lower slot numbers/PCI bus numbers */ | ||
148 | /* For CYC: No meaning */ | ||
149 | unsigned char chassis_num; /* 1 based Chassis number */ | ||
150 | /* For LookOut WPEGs this field indicates the */ | ||
151 | /* Expansion Chassis #, enumerated from Boot */ | ||
152 | /* Node WPEG external port, then Boot Node CYC */ | ||
153 | /* external port, then Next Vigil chassis WPEG */ | ||
154 | /* external port, etc. */ | ||
155 | /* Shared Lookouts have only 1 chassis number (the */ | ||
156 | /* first one assigned) */ | ||
157 | } __attribute__((packed)); | ||
158 | |||
159 | |||
160 | typedef enum { | ||
161 | CompatTwister = 0, /* Compatibility Twister */ | ||
162 | AltTwister = 1, /* Alternate Twister of internal 8-way */ | ||
163 | CompatCyclone = 2, /* Compatibility Cyclone */ | ||
164 | AltCyclone = 3, /* Alternate Cyclone of internal 8-way */ | ||
165 | CompatWPEG = 4, /* Compatibility WPEG */ | ||
166 | AltWPEG = 5, /* Second Planar WPEG */ | ||
167 | LookOutAWPEG = 6, /* LookOut WPEG */ | ||
168 | LookOutBWPEG = 7, /* LookOut WPEG */ | ||
169 | } node_type; | ||
170 | |||
171 | static inline int is_WPEG(struct rio_detail *rio){ | ||
172 | return (rio->type == CompatWPEG || rio->type == AltWPEG || | ||
173 | rio->type == LookOutAWPEG || rio->type == LookOutBWPEG); | ||
174 | } | ||
175 | |||
176 | #define SUMMIT_APIC_DFR_VALUE (APIC_DFR_CLUSTER) | ||
177 | |||
178 | static const struct cpumask *summit_target_cpus(void) | ||
179 | { | ||
180 | /* CPU_MASK_ALL (0xff) has undefined behaviour with | ||
181 | * dest_LowestPrio mode logical clustered apic interrupt routing | ||
182 | * Just start on cpu 0. IRQ balancing will spread load | ||
183 | */ | ||
184 | return cpumask_of(0); | ||
185 | } | ||
186 | |||
187 | static unsigned long summit_check_apicid_used(physid_mask_t *map, int apicid) | ||
188 | { | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | /* we don't use the phys_cpu_present_map to indicate apicid presence */ | ||
193 | static unsigned long summit_check_apicid_present(int bit) | ||
194 | { | ||
195 | return 1; | ||
196 | } | ||
197 | |||
198 | static int summit_early_logical_apicid(int cpu) | ||
199 | { | ||
200 | int count = 0; | ||
201 | u8 my_id = early_per_cpu(x86_cpu_to_apicid, cpu); | ||
202 | u8 my_cluster = APIC_CLUSTER(my_id); | ||
203 | #ifdef CONFIG_SMP | ||
204 | u8 lid; | ||
205 | int i; | ||
206 | |||
207 | /* Create logical APIC IDs by counting CPUs already in cluster. */ | ||
208 | for (count = 0, i = nr_cpu_ids; --i >= 0; ) { | ||
209 | lid = early_per_cpu(x86_cpu_to_logical_apicid, i); | ||
210 | if (lid != BAD_APICID && APIC_CLUSTER(lid) == my_cluster) | ||
211 | ++count; | ||
212 | } | ||
213 | #endif | ||
214 | /* We only have a 4 wide bitmap in cluster mode. If a deranged | ||
215 | * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */ | ||
216 | BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT); | ||
217 | return my_cluster | (1UL << count); | ||
218 | } | ||
219 | |||
220 | static void summit_init_apic_ldr(void) | ||
221 | { | ||
222 | int cpu = smp_processor_id(); | ||
223 | unsigned long id = early_per_cpu(x86_cpu_to_logical_apicid, cpu); | ||
224 | unsigned long val; | ||
225 | |||
226 | apic_write(APIC_DFR, SUMMIT_APIC_DFR_VALUE); | ||
227 | val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; | ||
228 | val |= SET_APIC_LOGICAL_ID(id); | ||
229 | apic_write(APIC_LDR, val); | ||
230 | } | ||
231 | |||
232 | static int summit_apic_id_registered(void) | ||
233 | { | ||
234 | return 1; | ||
235 | } | ||
236 | |||
237 | static void summit_setup_apic_routing(void) | ||
238 | { | ||
239 | pr_info("Enabling APIC mode: Summit. Using %d I/O APICs\n", | ||
240 | nr_ioapics); | ||
241 | } | ||
242 | |||
243 | static int summit_cpu_present_to_apicid(int mps_cpu) | ||
244 | { | ||
245 | if (mps_cpu < nr_cpu_ids) | ||
246 | return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu); | ||
247 | else | ||
248 | return BAD_APICID; | ||
249 | } | ||
250 | |||
251 | static void summit_ioapic_phys_id_map(physid_mask_t *phys_id_map, physid_mask_t *retmap) | ||
252 | { | ||
253 | /* For clustered we don't have a good way to do this yet - hack */ | ||
254 | physids_promote(0x0FL, retmap); | ||
255 | } | ||
256 | |||
257 | static void summit_apicid_to_cpu_present(int apicid, physid_mask_t *retmap) | ||
258 | { | ||
259 | physid_set_mask_of_physid(0, retmap); | ||
260 | } | ||
261 | |||
262 | static int summit_check_phys_apicid_present(int physical_apicid) | ||
263 | { | ||
264 | return 1; | ||
265 | } | ||
266 | |||
267 | static inline int | ||
268 | summit_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) | ||
269 | { | ||
270 | unsigned int round = 0; | ||
271 | unsigned int cpu, apicid = 0; | ||
272 | |||
273 | /* | ||
274 | * The cpus in the mask must all be on the apic cluster. | ||
275 | */ | ||
276 | for_each_cpu_and(cpu, cpumask, cpu_online_mask) { | ||
277 | int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu); | ||
278 | |||
279 | if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { | ||
280 | pr_err("Not a valid mask!\n"); | ||
281 | return -EINVAL; | ||
282 | } | ||
283 | apicid |= new_apicid; | ||
284 | round++; | ||
285 | } | ||
286 | if (!round) | ||
287 | return -EINVAL; | ||
288 | *dest_id = apicid; | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int | ||
293 | summit_cpu_mask_to_apicid_and(const struct cpumask *inmask, | ||
294 | const struct cpumask *andmask, | ||
295 | unsigned int *apicid) | ||
296 | { | ||
297 | cpumask_var_t cpumask; | ||
298 | *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); | ||
299 | |||
300 | if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) | ||
301 | return 0; | ||
302 | |||
303 | cpumask_and(cpumask, inmask, andmask); | ||
304 | summit_cpu_mask_to_apicid(cpumask, apicid); | ||
305 | |||
306 | free_cpumask_var(cpumask); | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * cpuid returns the value latched in the HW at reset, not the APIC ID | ||
313 | * register's value. For any box whose BIOS changes APIC IDs, like | ||
314 | * clustered APIC systems, we must use hard_smp_processor_id. | ||
315 | * | ||
316 | * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID. | ||
317 | */ | ||
318 | static int summit_phys_pkg_id(int cpuid_apic, int index_msb) | ||
319 | { | ||
320 | return hard_smp_processor_id() >> index_msb; | ||
321 | } | ||
322 | |||
323 | static int probe_summit(void) | ||
324 | { | ||
325 | /* probed later in mptable/ACPI hooks */ | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | #ifdef CONFIG_X86_SUMMIT_NUMA | ||
330 | static struct rio_table_hdr *rio_table_hdr; | ||
331 | static struct scal_detail *scal_devs[MAX_NUMNODES]; | ||
332 | static struct rio_detail *rio_devs[MAX_NUMNODES*4]; | ||
333 | |||
334 | #ifndef CONFIG_X86_NUMAQ | ||
335 | static int mp_bus_id_to_node[MAX_MP_BUSSES]; | ||
336 | #endif | ||
337 | |||
338 | static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus) | ||
339 | { | ||
340 | int twister = 0, node = 0; | ||
341 | int i, bus, num_buses; | ||
342 | |||
343 | for (i = 0; i < rio_table_hdr->num_rio_dev; i++) { | ||
344 | if (rio_devs[i]->node_id == rio_devs[wpeg_num]->owner_id) { | ||
345 | twister = rio_devs[i]->owner_id; | ||
346 | break; | ||
347 | } | ||
348 | } | ||
349 | if (i == rio_table_hdr->num_rio_dev) { | ||
350 | pr_err("Couldn't find owner Cyclone for Winnipeg!\n"); | ||
351 | return last_bus; | ||
352 | } | ||
353 | |||
354 | for (i = 0; i < rio_table_hdr->num_scal_dev; i++) { | ||
355 | if (scal_devs[i]->node_id == twister) { | ||
356 | node = scal_devs[i]->node_id; | ||
357 | break; | ||
358 | } | ||
359 | } | ||
360 | if (i == rio_table_hdr->num_scal_dev) { | ||
361 | pr_err("Couldn't find owner Twister for Cyclone!\n"); | ||
362 | return last_bus; | ||
363 | } | ||
364 | |||
365 | switch (rio_devs[wpeg_num]->type) { | ||
366 | case CompatWPEG: | ||
367 | /* | ||
368 | * The Compatibility Winnipeg controls the 2 legacy buses, | ||
369 | * the 66MHz PCI bus [2 slots] and the 2 "extra" buses in case | ||
370 | * a PCI-PCI bridge card is used in either slot: total 5 buses. | ||
371 | */ | ||
372 | num_buses = 5; | ||
373 | break; | ||
374 | case AltWPEG: | ||
375 | /* | ||
376 | * The Alternate Winnipeg controls the 2 133MHz buses [1 slot | ||
377 | * each], their 2 "extra" buses, the 100MHz bus [2 slots] and | ||
378 | * the "extra" buses for each of those slots: total 7 buses. | ||
379 | */ | ||
380 | num_buses = 7; | ||
381 | break; | ||
382 | case LookOutAWPEG: | ||
383 | case LookOutBWPEG: | ||
384 | /* | ||
385 | * A Lookout Winnipeg controls 3 100MHz buses [2 slots each] | ||
386 | * & the "extra" buses for each of those slots: total 9 buses. | ||
387 | */ | ||
388 | num_buses = 9; | ||
389 | break; | ||
390 | default: | ||
391 | pr_info("Unsupported Winnipeg type!\n"); | ||
392 | return last_bus; | ||
393 | } | ||
394 | |||
395 | for (bus = last_bus; bus < last_bus + num_buses; bus++) | ||
396 | mp_bus_id_to_node[bus] = node; | ||
397 | return bus; | ||
398 | } | ||
399 | |||
400 | static int build_detail_arrays(void) | ||
401 | { | ||
402 | unsigned long ptr; | ||
403 | int i, scal_detail_size, rio_detail_size; | ||
404 | |||
405 | if (rio_table_hdr->num_scal_dev > MAX_NUMNODES) { | ||
406 | pr_warn("MAX_NUMNODES too low! Defined as %d, but system has %d nodes\n", | ||
407 | MAX_NUMNODES, rio_table_hdr->num_scal_dev); | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | switch (rio_table_hdr->version) { | ||
412 | default: | ||
413 | pr_warn("Invalid Rio Grande Table Version: %d\n", | ||
414 | rio_table_hdr->version); | ||
415 | return 0; | ||
416 | case 2: | ||
417 | scal_detail_size = 11; | ||
418 | rio_detail_size = 13; | ||
419 | break; | ||
420 | case 3: | ||
421 | scal_detail_size = 12; | ||
422 | rio_detail_size = 15; | ||
423 | break; | ||
424 | } | ||
425 | |||
426 | ptr = (unsigned long)rio_table_hdr + 3; | ||
427 | for (i = 0; i < rio_table_hdr->num_scal_dev; i++, ptr += scal_detail_size) | ||
428 | scal_devs[i] = (struct scal_detail *)ptr; | ||
429 | |||
430 | for (i = 0; i < rio_table_hdr->num_rio_dev; i++, ptr += rio_detail_size) | ||
431 | rio_devs[i] = (struct rio_detail *)ptr; | ||
432 | |||
433 | return 1; | ||
434 | } | ||
435 | |||
436 | void setup_summit(void) | ||
437 | { | ||
438 | unsigned long ptr; | ||
439 | unsigned short offset; | ||
440 | int i, next_wpeg, next_bus = 0; | ||
441 | |||
442 | /* The pointer to the EBDA is stored in the word @ phys 0x40E(40:0E) */ | ||
443 | ptr = get_bios_ebda(); | ||
444 | ptr = (unsigned long)phys_to_virt(ptr); | ||
445 | |||
446 | rio_table_hdr = NULL; | ||
447 | offset = 0x180; | ||
448 | while (offset) { | ||
449 | /* The block id is stored in the 2nd word */ | ||
450 | if (*((unsigned short *)(ptr + offset + 2)) == 0x4752) { | ||
451 | /* set the pointer past the offset & block id */ | ||
452 | rio_table_hdr = (struct rio_table_hdr *)(ptr + offset + 4); | ||
453 | break; | ||
454 | } | ||
455 | /* The next offset is stored in the 1st word. 0 means no more */ | ||
456 | offset = *((unsigned short *)(ptr + offset)); | ||
457 | } | ||
458 | if (!rio_table_hdr) { | ||
459 | pr_err("Unable to locate Rio Grande Table in EBDA - bailing!\n"); | ||
460 | return; | ||
461 | } | ||
462 | |||
463 | if (!build_detail_arrays()) | ||
464 | return; | ||
465 | |||
466 | /* The first Winnipeg we're looking for has an index of 0 */ | ||
467 | next_wpeg = 0; | ||
468 | do { | ||
469 | for (i = 0; i < rio_table_hdr->num_rio_dev; i++) { | ||
470 | if (is_WPEG(rio_devs[i]) && rio_devs[i]->WP_index == next_wpeg) { | ||
471 | /* It's the Winnipeg we're looking for! */ | ||
472 | next_bus = setup_pci_node_map_for_wpeg(i, next_bus); | ||
473 | next_wpeg++; | ||
474 | break; | ||
475 | } | ||
476 | } | ||
477 | /* | ||
478 | * If we go through all Rio devices and don't find one with | ||
479 | * the next index, it means we've found all the Winnipegs, | ||
480 | * and thus all the PCI buses. | ||
481 | */ | ||
482 | if (i == rio_table_hdr->num_rio_dev) | ||
483 | next_wpeg = 0; | ||
484 | } while (next_wpeg != 0); | ||
485 | } | ||
486 | #endif | ||
487 | |||
488 | static struct apic apic_summit = { | ||
489 | |||
490 | .name = "summit", | ||
491 | .probe = probe_summit, | ||
492 | .acpi_madt_oem_check = summit_acpi_madt_oem_check, | ||
493 | .apic_id_valid = default_apic_id_valid, | ||
494 | .apic_id_registered = summit_apic_id_registered, | ||
495 | |||
496 | .irq_delivery_mode = dest_LowestPrio, | ||
497 | /* logical delivery broadcast to all CPUs: */ | ||
498 | .irq_dest_mode = 1, | ||
499 | |||
500 | .target_cpus = summit_target_cpus, | ||
501 | .disable_esr = 1, | ||
502 | .dest_logical = APIC_DEST_LOGICAL, | ||
503 | .check_apicid_used = summit_check_apicid_used, | ||
504 | .check_apicid_present = summit_check_apicid_present, | ||
505 | |||
506 | .vector_allocation_domain = flat_vector_allocation_domain, | ||
507 | .init_apic_ldr = summit_init_apic_ldr, | ||
508 | |||
509 | .ioapic_phys_id_map = summit_ioapic_phys_id_map, | ||
510 | .setup_apic_routing = summit_setup_apic_routing, | ||
511 | .multi_timer_check = NULL, | ||
512 | .cpu_present_to_apicid = summit_cpu_present_to_apicid, | ||
513 | .apicid_to_cpu_present = summit_apicid_to_cpu_present, | ||
514 | .setup_portio_remap = NULL, | ||
515 | .check_phys_apicid_present = summit_check_phys_apicid_present, | ||
516 | .enable_apic_mode = NULL, | ||
517 | .phys_pkg_id = summit_phys_pkg_id, | ||
518 | .mps_oem_check = summit_mps_oem_check, | ||
519 | |||
520 | .get_apic_id = summit_get_apic_id, | ||
521 | .set_apic_id = NULL, | ||
522 | .apic_id_mask = 0xFF << 24, | ||
523 | |||
524 | .cpu_mask_to_apicid_and = summit_cpu_mask_to_apicid_and, | ||
525 | |||
526 | .send_IPI_mask = summit_send_IPI_mask, | ||
527 | .send_IPI_mask_allbutself = NULL, | ||
528 | .send_IPI_allbutself = summit_send_IPI_allbutself, | ||
529 | .send_IPI_all = summit_send_IPI_all, | ||
530 | .send_IPI_self = default_send_IPI_self, | ||
531 | |||
532 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, | ||
533 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, | ||
534 | |||
535 | .wait_for_init_deassert = true, | ||
536 | .smp_callin_clear_local_apic = NULL, | ||
537 | .inquire_remote_apic = default_inquire_remote_apic, | ||
538 | |||
539 | .read = native_apic_mem_read, | ||
540 | .write = native_apic_mem_write, | ||
541 | .eoi_write = native_apic_mem_write, | ||
542 | .icr_read = native_apic_icr_read, | ||
543 | .icr_write = native_apic_icr_write, | ||
544 | .wait_icr_idle = native_apic_wait_icr_idle, | ||
545 | .safe_wait_icr_idle = native_safe_apic_wait_icr_idle, | ||
546 | |||
547 | .x86_32_early_logical_apicid = summit_early_logical_apicid, | ||
548 | }; | ||
549 | |||
550 | apic_driver(apic_summit); | ||
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 897d6201ef10..a80029035bf2 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -274,10 +274,6 @@ static void intel_workarounds(struct cpuinfo_x86 *c) | |||
274 | } | 274 | } |
275 | #endif | 275 | #endif |
276 | 276 | ||
277 | #ifdef CONFIG_X86_NUMAQ | ||
278 | numaq_tsc_disable(); | ||
279 | #endif | ||
280 | |||
281 | intel_smp_check(c); | 277 | intel_smp_check(c); |
282 | } | 278 | } |
283 | #else | 279 | #else |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index fa511acff7e6..09c76d265550 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -869,7 +869,6 @@ void __init setup_arch(char **cmdline_p) | |||
869 | 869 | ||
870 | #ifdef CONFIG_X86_32 | 870 | #ifdef CONFIG_X86_32 |
871 | memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); | 871 | memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); |
872 | visws_early_detect(); | ||
873 | 872 | ||
874 | /* | 873 | /* |
875 | * copy kernel address range established so far and switch | 874 | * copy kernel address range established so far and switch |