aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yhlu.kernel@gmail.com>2008-07-19 21:01:16 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-20 03:25:52 -0400
commit64898a8bad8c94ad7a4bd5cc86b66edfbb081f4a (patch)
tree013c56a97a533c0843d28d838bc94e6de3da9e2c
parent3c9cb6de1e5ad37d1558fdb0d9d2bed5a7bac0d9 (diff)
x86: extend and use x86_quirks to clean up NUMAQ code
add these new x86_quirks methods: int *mpc_record; int (*mpc_apic_id)(struct mpc_config_processor *m); void (*mpc_oem_bus_info)(struct mpc_config_bus *m, char *name); void (*mpc_oem_pci_bus)(struct mpc_config_bus *m); void (*smp_read_mpc_oem)(struct mp_config_oemtable *oemtable, unsigned short oemsize); ... and move NUMAQ related mps table handling to numaq_32.c. also move the call to smp_read_mpc_oem() to smp_read_mpc() directly. Should not change functionality, albeit it would be nice to get it tested on real NUMAQ as well ... Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/mpparse.c191
-rw-r--r--arch/x86/kernel/numaq_32.c190
-rw-r--r--include/asm-x86/mach-generic/mach_mpspec.h2
-rw-r--r--include/asm-x86/setup.h10
4 files changed, 212 insertions, 181 deletions
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 3cbd2df3abe4..6ae005ccaed8 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -49,76 +49,6 @@ static int __init mpf_checksum(unsigned char *mp, int len)
49 return sum & 0xFF; 49 return sum & 0xFF;
50} 50}
51 51
52#ifdef CONFIG_X86_NUMAQ
53int found_numaq;
54/*
55 * Have to match translation table entries to main table entries by counter
56 * hence the mpc_record variable .... can't see a less disgusting way of
57 * doing this ....
58 */
59struct mpc_config_translation {
60 unsigned char mpc_type;
61 unsigned char trans_len;
62 unsigned char trans_type;
63 unsigned char trans_quad;
64 unsigned char trans_global;
65 unsigned char trans_local;
66 unsigned short trans_reserved;
67};
68
69
70static int mpc_record;
71static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY]
72 __cpuinitdata;
73
74static inline int generate_logical_apicid(int quad, int phys_apicid)
75{
76 return (quad << 4) + (phys_apicid ? phys_apicid << 1 : 1);
77}
78
79
80static inline int mpc_apic_id(struct mpc_config_processor *m,
81 struct mpc_config_translation *translation_record)
82{
83 int quad = translation_record->trans_quad;
84 int logical_apicid = generate_logical_apicid(quad, m->mpc_apicid);
85
86 printk(KERN_DEBUG "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n",
87 m->mpc_apicid,
88 (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
89 (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
90 m->mpc_apicver, quad, logical_apicid);
91 return logical_apicid;
92}
93
94int mp_bus_id_to_node[MAX_MP_BUSSES];
95
96int mp_bus_id_to_local[MAX_MP_BUSSES];
97
98static void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
99 struct mpc_config_translation *translation)
100{
101 int quad = translation->trans_quad;
102 int local = translation->trans_local;
103
104 mp_bus_id_to_node[m->mpc_busid] = quad;
105 mp_bus_id_to_local[m->mpc_busid] = local;
106 printk(KERN_INFO "Bus #%d is %s (node %d)\n",
107 m->mpc_busid, name, quad);
108}
109
110int quad_local_to_mp_bus_id [NR_CPUS/4][4];
111static void mpc_oem_pci_bus(struct mpc_config_bus *m,
112 struct mpc_config_translation *translation)
113{
114 int quad = translation->trans_quad;
115 int local = translation->trans_local;
116
117 quad_local_to_mp_bus_id[quad][local] = m->mpc_busid;
118}
119
120#endif
121
122static void __cpuinit MP_processor_info(struct mpc_config_processor *m) 52static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
123{ 53{
124 int apicid; 54 int apicid;
@@ -128,14 +58,12 @@ static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
128 disabled_cpus++; 58 disabled_cpus++;
129 return; 59 return;
130 } 60 }
131#ifdef CONFIG_X86_NUMAQ 61
132 if (found_numaq) 62 if (x86_quirks->mpc_apic_id)
133 apicid = mpc_apic_id(m, translation_table[mpc_record]); 63 apicid = x86_quirks->mpc_apic_id(m);
134 else 64 else
135 apicid = m->mpc_apicid; 65 apicid = m->mpc_apicid;
136#else 66
137 apicid = m->mpc_apicid;
138#endif
139 if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { 67 if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
140 bootup_cpu = " (Bootup-CPU)"; 68 bootup_cpu = " (Bootup-CPU)";
141 boot_cpu_physical_apicid = m->mpc_apicid; 69 boot_cpu_physical_apicid = m->mpc_apicid;
@@ -152,12 +80,10 @@ static void __init MP_bus_info(struct mpc_config_bus *m)
152 memcpy(str, m->mpc_bustype, 6); 80 memcpy(str, m->mpc_bustype, 6);
153 str[6] = 0; 81 str[6] = 0;
154 82
155#ifdef CONFIG_X86_NUMAQ 83 if (x86_quirks->mpc_oem_bus_info)
156 if (found_numaq) 84 x86_quirks->mpc_oem_bus_info(m, str);
157 mpc_oem_bus_info(m, str, translation_table[mpc_record]); 85 else
158#else 86 printk(KERN_INFO "Bus #%d is %s\n", m->mpc_busid, str);
159 printk(KERN_INFO "Bus #%d is %s\n", m->mpc_busid, str);
160#endif
161 87
162#if MAX_MP_BUSSES < 256 88#if MAX_MP_BUSSES < 256
163 if (m->mpc_busid >= MAX_MP_BUSSES) { 89 if (m->mpc_busid >= MAX_MP_BUSSES) {
@@ -174,10 +100,9 @@ static void __init MP_bus_info(struct mpc_config_bus *m)
174 mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA; 100 mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
175#endif 101#endif
176 } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) { 102 } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
177#ifdef CONFIG_X86_NUMAQ 103 if (x86_quirks->mpc_oem_pci_bus)
178 if (found_numaq) 104 x86_quirks->mpc_oem_pci_bus(m);
179 mpc_oem_pci_bus(m, translation_table[mpc_record]); 105
180#endif
181 clear_bit(m->mpc_busid, mp_bus_not_pci); 106 clear_bit(m->mpc_busid, mp_bus_not_pci);
182#if defined(CONFIG_EISA) || defined (CONFIG_MCA) 107#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
183 mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI; 108 mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
@@ -317,83 +242,6 @@ static void __init MP_lintsrc_info(struct mpc_config_lintsrc *m)
317 m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint); 242 m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
318} 243}
319 244
320#ifdef CONFIG_X86_NUMAQ
321static void __init MP_translation_info(struct mpc_config_translation *m)
322{
323 printk(KERN_INFO
324 "Translation: record %d, type %d, quad %d, global %d, local %d\n",
325 mpc_record, m->trans_type, m->trans_quad, m->trans_global,
326 m->trans_local);
327
328 if (mpc_record >= MAX_MPC_ENTRY)
329 printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
330 else
331 translation_table[mpc_record] = m; /* stash this for later */
332 if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
333 node_set_online(m->trans_quad);
334}
335
336/*
337 * Read/parse the MPC oem tables
338 */
339
340static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
341 unsigned short oemsize)
342{
343 int count = sizeof(*oemtable); /* the header size */
344 unsigned char *oemptr = ((unsigned char *)oemtable) + count;
345
346 mpc_record = 0;
347 printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n",
348 oemtable);
349 if (memcmp(oemtable->oem_signature, MPC_OEM_SIGNATURE, 4)) {
350 printk(KERN_WARNING
351 "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
352 oemtable->oem_signature[0], oemtable->oem_signature[1],
353 oemtable->oem_signature[2], oemtable->oem_signature[3]);
354 return;
355 }
356 if (mpf_checksum((unsigned char *)oemtable, oemtable->oem_length)) {
357 printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
358 return;
359 }
360 while (count < oemtable->oem_length) {
361 switch (*oemptr) {
362 case MP_TRANSLATION:
363 {
364 struct mpc_config_translation *m =
365 (struct mpc_config_translation *)oemptr;
366 MP_translation_info(m);
367 oemptr += sizeof(*m);
368 count += sizeof(*m);
369 ++mpc_record;
370 break;
371 }
372 default:
373 {
374 printk(KERN_WARNING
375 "Unrecognised OEM table entry type! - %d\n",
376 (int)*oemptr);
377 return;
378 }
379 }
380 }
381}
382
383void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
384 char *productid)
385{
386 if (strncmp(oem, "IBM NUMA", 8))
387 printk("Warning! Not a NUMA-Q system!\n");
388 else
389 found_numaq = 1;
390
391 if (mpc->mpc_oemptr)
392 smp_read_mpc_oem((struct mp_config_oemtable *)mpc->mpc_oemptr,
393 mpc->mpc_oemsize);
394}
395#endif /* CONFIG_X86_NUMAQ */
396
397/* 245/*
398 * Read/parse the MPC 246 * Read/parse the MPC
399 */ 247 */
@@ -458,7 +306,6 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
458 } else 306 } else
459 mps_oem_check(mpc, oem, str); 307 mps_oem_check(mpc, oem, str);
460#endif 308#endif
461
462 /* save the local APIC address, it might be non-default */ 309 /* save the local APIC address, it might be non-default */
463 if (!acpi_lapic) 310 if (!acpi_lapic)
464 mp_lapic_addr = mpc->mpc_lapic; 311 mp_lapic_addr = mpc->mpc_lapic;
@@ -466,12 +313,17 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
466 if (early) 313 if (early)
467 return 1; 314 return 1;
468 315
316 if (mpc->mpc_oemptr && x86_quirks->smp_read_mpc_oem) {
317 struct mp_config_oemtable *oem_table = (struct mp_config_oemtable *)(unsigned long)mpc->mpc_oemptr;
318 x86_quirks->smp_read_mpc_oem(oem_table, mpc->mpc_oemsize);
319 }
320
469 /* 321 /*
470 * Now process the configuration blocks. 322 * Now process the configuration blocks.
471 */ 323 */
472#ifdef CONFIG_X86_NUMAQ 324 if (x86_quirks->mpc_record)
473 mpc_record = 0; 325 *x86_quirks->mpc_record = 0;
474#endif 326
475 while (count < mpc->mpc_length) { 327 while (count < mpc->mpc_length) {
476 switch (*mpt) { 328 switch (*mpt) {
477 case MP_PROCESSOR: 329 case MP_PROCESSOR:
@@ -537,9 +389,8 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
537 count = mpc->mpc_length; 389 count = mpc->mpc_length;
538 break; 390 break;
539 } 391 }
540#ifdef CONFIG_X86_NUMAQ 392 if (x86_quirks->mpc_record)
541 ++mpc_record; 393 (*x86_quirks->mpc_record)++;
542#endif
543 } 394 }
544 395
545#ifdef CONFIG_X86_GENERICARCH 396#ifdef CONFIG_X86_GENERICARCH
diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c
index a23e8233b9ac..7f4e00d1d893 100644
--- a/arch/x86/kernel/numaq_32.c
+++ b/arch/x86/kernel/numaq_32.c
@@ -33,6 +33,7 @@
33#include <asm/processor.h> 33#include <asm/processor.h>
34#include <asm/mpspec.h> 34#include <asm/mpspec.h>
35#include <asm/e820.h> 35#include <asm/e820.h>
36#include <asm/setup.h>
36 37
37#define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT)) 38#define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT))
38 39
@@ -71,6 +72,181 @@ static void __init smp_dump_qct(void)
71 } 72 }
72} 73}
73 74
75
76void __init numaq_tsc_disable(void)
77{
78 if (!found_numaq)
79 return;
80
81 if (num_online_nodes() > 1) {
82 printk(KERN_DEBUG "NUMAQ: disabling TSC\n");
83 setup_clear_cpu_cap(X86_FEATURE_TSC);
84 }
85}
86
87int found_numaq;
88/*
89 * Have to match translation table entries to main table entries by counter
90 * hence the mpc_record variable .... can't see a less disgusting way of
91 * doing this ....
92 */
93struct mpc_config_translation {
94 unsigned char mpc_type;
95 unsigned char trans_len;
96 unsigned char trans_type;
97 unsigned char trans_quad;
98 unsigned char trans_global;
99 unsigned char trans_local;
100 unsigned short trans_reserved;
101};
102
103/* x86_quirks member */
104static int mpc_record;
105static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY]
106 __cpuinitdata;
107
108static inline int generate_logical_apicid(int quad, int phys_apicid)
109{
110 return (quad << 4) + (phys_apicid ? phys_apicid << 1 : 1);
111}
112
113/* x86_quirks member */
114static int mpc_apic_id(struct mpc_config_processor *m)
115{
116 int quad = translation_table[mpc_record]->trans_quad;
117 int logical_apicid = generate_logical_apicid(quad, m->mpc_apicid);
118
119 printk(KERN_DEBUG "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n",
120 m->mpc_apicid,
121 (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
122 (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
123 m->mpc_apicver, quad, logical_apicid);
124 return logical_apicid;
125}
126
127int mp_bus_id_to_node[MAX_MP_BUSSES];
128
129int mp_bus_id_to_local[MAX_MP_BUSSES];
130
131/* x86_quirks member */
132static void mpc_oem_bus_info(struct mpc_config_bus *m, char *name)
133{
134 int quad = translation_table[mpc_record]->trans_quad;
135 int local = translation_table[mpc_record]->trans_local;
136
137 mp_bus_id_to_node[m->mpc_busid] = quad;
138 mp_bus_id_to_local[m->mpc_busid] = local;
139 printk(KERN_INFO "Bus #%d is %s (node %d)\n",
140 m->mpc_busid, name, quad);
141}
142
143int quad_local_to_mp_bus_id [NR_CPUS/4][4];
144
145/* x86_quirks member */
146static void mpc_oem_pci_bus(struct mpc_config_bus *m)
147{
148 int quad = translation_table[mpc_record]->trans_quad;
149 int local = translation_table[mpc_record]->trans_local;
150
151 quad_local_to_mp_bus_id[quad][local] = m->mpc_busid;
152}
153
154static void __init MP_translation_info(struct mpc_config_translation *m)
155{
156 printk(KERN_INFO
157 "Translation: record %d, type %d, quad %d, global %d, local %d\n",
158 mpc_record, m->trans_type, m->trans_quad, m->trans_global,
159 m->trans_local);
160
161 if (mpc_record >= MAX_MPC_ENTRY)
162 printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
163 else
164 translation_table[mpc_record] = m; /* stash this for later */
165 if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
166 node_set_online(m->trans_quad);
167}
168
169static int __init mpf_checksum(unsigned char *mp, int len)
170{
171 int sum = 0;
172
173 while (len--)
174 sum += *mp++;
175
176 return sum & 0xFF;
177}
178
179/*
180 * Read/parse the MPC oem tables
181 */
182
183static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
184 unsigned short oemsize)
185{
186 int count = sizeof(*oemtable); /* the header size */
187 unsigned char *oemptr = ((unsigned char *)oemtable) + count;
188
189 mpc_record = 0;
190 printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n",
191 oemtable);
192 if (memcmp(oemtable->oem_signature, MPC_OEM_SIGNATURE, 4)) {
193 printk(KERN_WARNING
194 "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
195 oemtable->oem_signature[0], oemtable->oem_signature[1],
196 oemtable->oem_signature[2], oemtable->oem_signature[3]);
197 return;
198 }
199 if (mpf_checksum((unsigned char *)oemtable, oemtable->oem_length)) {
200 printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
201 return;
202 }
203 while (count < oemtable->oem_length) {
204 switch (*oemptr) {
205 case MP_TRANSLATION:
206 {
207 struct mpc_config_translation *m =
208 (struct mpc_config_translation *)oemptr;
209 MP_translation_info(m);
210 oemptr += sizeof(*m);
211 count += sizeof(*m);
212 ++mpc_record;
213 break;
214 }
215 default:
216 {
217 printk(KERN_WARNING
218 "Unrecognised OEM table entry type! - %d\n",
219 (int)*oemptr);
220 return;
221 }
222 }
223 }
224}
225
226static struct x86_quirks numaq_x86_quirks __initdata = {
227 .arch_time_init = NULL,
228 .arch_pre_intr_init = NULL,
229 .arch_memory_setup = NULL,
230 .arch_intr_init = NULL,
231 .arch_trap_init = NULL,
232 .mach_get_smp_config = NULL,
233 .mach_find_smp_config = NULL,
234 .mpc_record = &mpc_record,
235 .mpc_apic_id = mpc_apic_id,
236 .mpc_oem_bus_info = mpc_oem_bus_info,
237 .mpc_oem_pci_bus = mpc_oem_pci_bus,
238 .smp_read_mpc_oem = smp_read_mpc_oem,
239};
240
241void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
242 char *productid)
243{
244 if (strncmp(oem, "IBM NUMA", 8))
245 printk("Warning! Not a NUMA-Q system!\n");
246 else
247 found_numaq = 1;
248}
249
74static __init void early_check_numaq(void) 250static __init void early_check_numaq(void)
75{ 251{
76 /* 252 /*
@@ -82,6 +258,9 @@ static __init void early_check_numaq(void)
82 */ 258 */
83 if (smp_found_config) 259 if (smp_found_config)
84 early_get_smp_config(); 260 early_get_smp_config();
261
262 if (found_numaq)
263 x86_quirks = &numaq_x86_quirks;
85} 264}
86 265
87int __init get_memcfg_numaq(void) 266int __init get_memcfg_numaq(void)
@@ -92,14 +271,3 @@ int __init get_memcfg_numaq(void)
92 smp_dump_qct(); 271 smp_dump_qct();
93 return 1; 272 return 1;
94} 273}
95
96void __init numaq_tsc_disable(void)
97{
98 if (!found_numaq)
99 return;
100
101 if (num_online_nodes() > 1) {
102 printk(KERN_DEBUG "NUMAQ: disabling TSC\n");
103 setup_clear_cpu_cap(X86_FEATURE_TSC);
104 }
105}
diff --git a/include/asm-x86/mach-generic/mach_mpspec.h b/include/asm-x86/mach-generic/mach_mpspec.h
index 9ef0b941bb22..c83c120be538 100644
--- a/include/asm-x86/mach-generic/mach_mpspec.h
+++ b/include/asm-x86/mach-generic/mach_mpspec.h
@@ -7,4 +7,6 @@
7/* Maximum 256 PCI busses, plus 1 ISA bus in each of 4 cabinets. */ 7/* Maximum 256 PCI busses, plus 1 ISA bus in each of 4 cabinets. */
8#define MAX_MP_BUSSES 260 8#define MAX_MP_BUSSES 260
9 9
10extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
11 char *productid);
10#endif /* __ASM_MACH_MPSPEC_H */ 12#endif /* __ASM_MACH_MPSPEC_H */
diff --git a/include/asm-x86/setup.h b/include/asm-x86/setup.h
index 66191d0de3c9..2585075da9b4 100644
--- a/include/asm-x86/setup.h
+++ b/include/asm-x86/setup.h
@@ -19,6 +19,9 @@ static inline int is_visws_box(void) { return 0; }
19/* 19/*
20 * Any setup quirks to be performed? 20 * Any setup quirks to be performed?
21 */ 21 */
22struct mpc_config_processor;
23struct mpc_config_bus;
24struct mp_config_oemtable;
22struct x86_quirks { 25struct x86_quirks {
23 int (*arch_time_init)(void); 26 int (*arch_time_init)(void);
24 int (*arch_pre_intr_init)(void); 27 int (*arch_pre_intr_init)(void);
@@ -27,6 +30,13 @@ struct x86_quirks {
27 char * (*arch_memory_setup)(void); 30 char * (*arch_memory_setup)(void);
28 int (*mach_get_smp_config)(unsigned int early); 31 int (*mach_get_smp_config)(unsigned int early);
29 int (*mach_find_smp_config)(unsigned int reserve); 32 int (*mach_find_smp_config)(unsigned int reserve);
33
34 int *mpc_record;
35 int (*mpc_apic_id)(struct mpc_config_processor *m);
36 void (*mpc_oem_bus_info)(struct mpc_config_bus *m, char *name);
37 void (*mpc_oem_pci_bus)(struct mpc_config_bus *m);
38 void (*smp_read_mpc_oem)(struct mp_config_oemtable *oemtable,
39 unsigned short oemsize);
30}; 40};
31 41
32extern struct x86_quirks *x86_quirks; 42extern struct x86_quirks *x86_quirks;