diff options
-rw-r--r-- | arch/x86/kernel/numaq_32.c | 195 |
1 files changed, 100 insertions, 95 deletions
diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c index 15328500de6e..a4ea08a9ac94 100644 --- a/arch/x86/kernel/numaq_32.c +++ b/arch/x86/kernel/numaq_32.c | |||
@@ -22,21 +22,54 @@ | |||
22 | * | 22 | * |
23 | * Send feedback to <gone@us.ibm.com> | 23 | * Send feedback to <gone@us.ibm.com> |
24 | */ | 24 | */ |
25 | |||
26 | #include <linux/nodemask.h> | 25 | #include <linux/nodemask.h> |
27 | #include <linux/bootmem.h> | 26 | #include <linux/bootmem.h> |
27 | #include <linux/threads.h> | ||
28 | #include <linux/cpumask.h> | ||
29 | #include <linux/kernel.h> | ||
28 | #include <linux/mmzone.h> | 30 | #include <linux/mmzone.h> |
29 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/string.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/numa.h> | ||
35 | #include <linux/smp.h> | ||
30 | #include <linux/mm.h> | 36 | #include <linux/mm.h> |
31 | 37 | ||
32 | #include <asm/processor.h> | 38 | #include <asm/processor.h> |
33 | #include <asm/topology.h> | 39 | #include <asm/topology.h> |
34 | #include <asm/apic.h> | 40 | #include <asm/fixmap.h> |
41 | #include <asm/mpspec.h> | ||
35 | #include <asm/numaq.h> | 42 | #include <asm/numaq.h> |
36 | #include <asm/setup.h> | 43 | #include <asm/setup.h> |
44 | #include <asm/apic.h> | ||
37 | #include <asm/e820.h> | 45 | #include <asm/e820.h> |
46 | #include <asm/ipi.h> | ||
47 | #include <asm/io.h> | ||
38 | 48 | ||
39 | #define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT)) | 49 | #define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT)) |
50 | |||
51 | static inline void numaq_register_node(int node, struct sys_cfg_data *scd) | ||
52 | { | ||
53 | struct eachquadmem *eq = scd->eq + node; | ||
54 | |||
55 | node_set_online(node); | ||
56 | |||
57 | /* Convert to pages */ | ||
58 | node_start_pfn[node] = | ||
59 | MB_TO_PAGES(eq->hi_shrd_mem_start - eq->priv_mem_size); | ||
60 | |||
61 | node_end_pfn[node] = | ||
62 | MB_TO_PAGES(eq->hi_shrd_mem_start + eq->hi_shrd_mem_size); | ||
63 | |||
64 | e820_register_active_regions(node, node_start_pfn[node], | ||
65 | node_end_pfn[node]); | ||
66 | |||
67 | memory_present(node, node_start_pfn[node], node_end_pfn[node]); | ||
68 | |||
69 | node_remap_size[node] = node_memmap_size_bytes(node, | ||
70 | node_start_pfn[node], | ||
71 | node_end_pfn[node]); | ||
72 | } | ||
40 | 73 | ||
41 | /* | 74 | /* |
42 | * Function: smp_dump_qct() | 75 | * Function: smp_dump_qct() |
@@ -46,34 +79,18 @@ | |||
46 | */ | 79 | */ |
47 | static void __init smp_dump_qct(void) | 80 | static void __init smp_dump_qct(void) |
48 | { | 81 | { |
82 | struct sys_cfg_data *scd; | ||
49 | int node; | 83 | int node; |
50 | struct eachquadmem *eq; | 84 | |
51 | struct sys_cfg_data *scd = | 85 | scd = (void *)__va(SYS_CFG_DATA_PRIV_ADDR); |
52 | (struct sys_cfg_data *)__va(SYS_CFG_DATA_PRIV_ADDR); | ||
53 | 86 | ||
54 | nodes_clear(node_online_map); | 87 | nodes_clear(node_online_map); |
55 | for_each_node(node) { | 88 | for_each_node(node) { |
56 | if (scd->quads_present31_0 & (1 << node)) { | 89 | if (scd->quads_present31_0 & (1 << node)) |
57 | node_set_online(node); | 90 | numaq_register_node(node, scd); |
58 | eq = &scd->eq[node]; | ||
59 | /* Convert to pages */ | ||
60 | node_start_pfn[node] = MB_TO_PAGES( | ||
61 | eq->hi_shrd_mem_start - eq->priv_mem_size); | ||
62 | node_end_pfn[node] = MB_TO_PAGES( | ||
63 | eq->hi_shrd_mem_start + eq->hi_shrd_mem_size); | ||
64 | |||
65 | e820_register_active_regions(node, node_start_pfn[node], | ||
66 | node_end_pfn[node]); | ||
67 | memory_present(node, | ||
68 | node_start_pfn[node], node_end_pfn[node]); | ||
69 | node_remap_size[node] = node_memmap_size_bytes(node, | ||
70 | node_start_pfn[node], | ||
71 | node_end_pfn[node]); | ||
72 | } | ||
73 | } | 91 | } |
74 | } | 92 | } |
75 | 93 | ||
76 | |||
77 | void __cpuinit numaq_tsc_disable(void) | 94 | void __cpuinit numaq_tsc_disable(void) |
78 | { | 95 | { |
79 | if (!found_numaq) | 96 | if (!found_numaq) |
@@ -98,20 +115,20 @@ int found_numaq; | |||
98 | * hence the mpc_record variable .... can't see a less disgusting way of | 115 | * hence the mpc_record variable .... can't see a less disgusting way of |
99 | * doing this .... | 116 | * doing this .... |
100 | */ | 117 | */ |
101 | struct mpc_config_translation { | 118 | struct mpc_trans { |
102 | unsigned char mpc_type; | 119 | unsigned char mpc_type; |
103 | unsigned char trans_len; | 120 | unsigned char trans_len; |
104 | unsigned char trans_type; | 121 | unsigned char trans_type; |
105 | unsigned char trans_quad; | 122 | unsigned char trans_quad; |
106 | unsigned char trans_global; | 123 | unsigned char trans_global; |
107 | unsigned char trans_local; | 124 | unsigned char trans_local; |
108 | unsigned short trans_reserved; | 125 | unsigned short trans_reserved; |
109 | }; | 126 | }; |
110 | 127 | ||
111 | /* x86_quirks member */ | 128 | /* x86_quirks member */ |
112 | static int mpc_record; | 129 | static int mpc_record; |
113 | static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] | 130 | |
114 | __cpuinitdata; | 131 | static __cpuinitdata struct mpc_trans *translation_table[MAX_MPC_ENTRY]; |
115 | 132 | ||
116 | static inline int generate_logical_apicid(int quad, int phys_apicid) | 133 | static inline int generate_logical_apicid(int quad, int phys_apicid) |
117 | { | 134 | { |
@@ -124,10 +141,12 @@ static int mpc_apic_id(struct mpc_cpu *m) | |||
124 | int quad = translation_table[mpc_record]->trans_quad; | 141 | int quad = translation_table[mpc_record]->trans_quad; |
125 | int logical_apicid = generate_logical_apicid(quad, m->apicid); | 142 | int logical_apicid = generate_logical_apicid(quad, m->apicid); |
126 | 143 | ||
127 | printk(KERN_DEBUG "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n", | 144 | printk(KERN_DEBUG |
128 | m->apicid, (m->cpufeature & CPU_FAMILY_MASK) >> 8, | 145 | "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n", |
129 | (m->cpufeature & CPU_MODEL_MASK) >> 4, | 146 | m->apicid, (m->cpufeature & CPU_FAMILY_MASK) >> 8, |
130 | m->apicver, quad, logical_apicid); | 147 | (m->cpufeature & CPU_MODEL_MASK) >> 4, |
148 | m->apicver, quad, logical_apicid); | ||
149 | |||
131 | return logical_apicid; | 150 | return logical_apicid; |
132 | } | 151 | } |
133 | 152 | ||
@@ -143,11 +162,11 @@ static void mpc_oem_bus_info(struct mpc_bus *m, char *name) | |||
143 | 162 | ||
144 | mp_bus_id_to_node[m->busid] = quad; | 163 | mp_bus_id_to_node[m->busid] = quad; |
145 | mp_bus_id_to_local[m->busid] = local; | 164 | mp_bus_id_to_local[m->busid] = local; |
146 | printk(KERN_INFO "Bus #%d is %s (node %d)\n", | 165 | |
147 | m->busid, name, quad); | 166 | printk(KERN_INFO "Bus #%d is %s (node %d)\n", m->busid, name, quad); |
148 | } | 167 | } |
149 | 168 | ||
150 | int quad_local_to_mp_bus_id [NR_CPUS/4][4]; | 169 | int quad_local_to_mp_bus_id[NR_CPUS/4][4]; |
151 | 170 | ||
152 | /* x86_quirks member */ | 171 | /* x86_quirks member */ |
153 | static void mpc_oem_pci_bus(struct mpc_bus *m) | 172 | static void mpc_oem_pci_bus(struct mpc_bus *m) |
@@ -158,7 +177,7 @@ static void mpc_oem_pci_bus(struct mpc_bus *m) | |||
158 | quad_local_to_mp_bus_id[quad][local] = m->busid; | 177 | quad_local_to_mp_bus_id[quad][local] = m->busid; |
159 | } | 178 | } |
160 | 179 | ||
161 | static void __init MP_translation_info(struct mpc_config_translation *m) | 180 | static void __init MP_translation_info(struct mpc_trans *m) |
162 | { | 181 | { |
163 | printk(KERN_INFO | 182 | printk(KERN_INFO |
164 | "Translation: record %d, type %d, quad %d, global %d, local %d\n", | 183 | "Translation: record %d, type %d, quad %d, global %d, local %d\n", |
@@ -168,7 +187,8 @@ static void __init MP_translation_info(struct mpc_config_translation *m) | |||
168 | if (mpc_record >= MAX_MPC_ENTRY) | 187 | if (mpc_record >= MAX_MPC_ENTRY) |
169 | printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n"); | 188 | printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n"); |
170 | else | 189 | else |
171 | translation_table[mpc_record] = m; /* stash this for later */ | 190 | translation_table[mpc_record] = m; /* stash this for later */ |
191 | |||
172 | if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad)) | 192 | if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad)) |
173 | node_set_online(m->trans_quad); | 193 | node_set_online(m->trans_quad); |
174 | } | 194 | } |
@@ -186,16 +206,16 @@ static int __init mpf_checksum(unsigned char *mp, int len) | |||
186 | /* | 206 | /* |
187 | * Read/parse the MPC oem tables | 207 | * Read/parse the MPC oem tables |
188 | */ | 208 | */ |
189 | 209 | static void __init | |
190 | static void __init smp_read_mpc_oem(struct mpc_oemtable *oemtable, | 210 | smp_read_mpc_oem(struct mpc_oemtable *oemtable, unsigned short oemsize) |
191 | unsigned short oemsize) | ||
192 | { | 211 | { |
193 | int count = sizeof(*oemtable); /* the header size */ | 212 | int count = sizeof(*oemtable); /* the header size */ |
194 | unsigned char *oemptr = ((unsigned char *)oemtable) + count; | 213 | unsigned char *oemptr = ((unsigned char *)oemtable) + count; |
195 | 214 | ||
196 | mpc_record = 0; | 215 | mpc_record = 0; |
197 | printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", | 216 | printk(KERN_INFO |
198 | oemtable); | 217 | "Found an OEM MPC table at %8p - parsing it ... \n", oemtable); |
218 | |||
199 | if (memcmp(oemtable->signature, MPC_OEM_SIGNATURE, 4)) { | 219 | if (memcmp(oemtable->signature, MPC_OEM_SIGNATURE, 4)) { |
200 | printk(KERN_WARNING | 220 | printk(KERN_WARNING |
201 | "SMP mpc oemtable: bad signature [%c%c%c%c]!\n", | 221 | "SMP mpc oemtable: bad signature [%c%c%c%c]!\n", |
@@ -203,16 +223,18 @@ static void __init smp_read_mpc_oem(struct mpc_oemtable *oemtable, | |||
203 | oemtable->signature[2], oemtable->signature[3]); | 223 | oemtable->signature[2], oemtable->signature[3]); |
204 | return; | 224 | return; |
205 | } | 225 | } |
226 | |||
206 | if (mpf_checksum((unsigned char *)oemtable, oemtable->length)) { | 227 | if (mpf_checksum((unsigned char *)oemtable, oemtable->length)) { |
207 | printk(KERN_WARNING "SMP oem mptable: checksum error!\n"); | 228 | printk(KERN_WARNING "SMP oem mptable: checksum error!\n"); |
208 | return; | 229 | return; |
209 | } | 230 | } |
231 | |||
210 | while (count < oemtable->length) { | 232 | while (count < oemtable->length) { |
211 | switch (*oemptr) { | 233 | switch (*oemptr) { |
212 | case MP_TRANSLATION: | 234 | case MP_TRANSLATION: |
213 | { | 235 | { |
214 | struct mpc_config_translation *m = | 236 | struct mpc_trans *m = (void *)oemptr; |
215 | (struct mpc_config_translation *)oemptr; | 237 | |
216 | MP_translation_info(m); | 238 | MP_translation_info(m); |
217 | oemptr += sizeof(*m); | 239 | oemptr += sizeof(*m); |
218 | count += sizeof(*m); | 240 | count += sizeof(*m); |
@@ -220,12 +242,10 @@ static void __init smp_read_mpc_oem(struct mpc_oemtable *oemtable, | |||
220 | break; | 242 | break; |
221 | } | 243 | } |
222 | default: | 244 | default: |
223 | { | 245 | printk(KERN_WARNING |
224 | printk(KERN_WARNING | 246 | "Unrecognised OEM table entry type! - %d\n", |
225 | "Unrecognised OEM table entry type! - %d\n", | 247 | (int)*oemptr); |
226 | (int)*oemptr); | 248 | return; |
227 | return; | ||
228 | } | ||
229 | } | 249 | } |
230 | } | 250 | } |
231 | } | 251 | } |
@@ -244,21 +264,21 @@ static int __init numaq_update_genapic(void) | |||
244 | } | 264 | } |
245 | 265 | ||
246 | static struct x86_quirks numaq_x86_quirks __initdata = { | 266 | static struct x86_quirks numaq_x86_quirks __initdata = { |
247 | .arch_pre_time_init = numaq_pre_time_init, | 267 | .arch_pre_time_init = numaq_pre_time_init, |
248 | .arch_time_init = NULL, | 268 | .arch_time_init = NULL, |
249 | .arch_pre_intr_init = NULL, | 269 | .arch_pre_intr_init = NULL, |
250 | .arch_memory_setup = NULL, | 270 | .arch_memory_setup = NULL, |
251 | .arch_intr_init = NULL, | 271 | .arch_intr_init = NULL, |
252 | .arch_trap_init = NULL, | 272 | .arch_trap_init = NULL, |
253 | .mach_get_smp_config = NULL, | 273 | .mach_get_smp_config = NULL, |
254 | .mach_find_smp_config = NULL, | 274 | .mach_find_smp_config = NULL, |
255 | .mpc_record = &mpc_record, | 275 | .mpc_record = &mpc_record, |
256 | .mpc_apic_id = mpc_apic_id, | 276 | .mpc_apic_id = mpc_apic_id, |
257 | .mpc_oem_bus_info = mpc_oem_bus_info, | 277 | .mpc_oem_bus_info = mpc_oem_bus_info, |
258 | .mpc_oem_pci_bus = mpc_oem_pci_bus, | 278 | .mpc_oem_pci_bus = mpc_oem_pci_bus, |
259 | .smp_read_mpc_oem = smp_read_mpc_oem, | 279 | .smp_read_mpc_oem = smp_read_mpc_oem, |
260 | .setup_ioapic_ids = numaq_setup_ioapic_ids, | 280 | .setup_ioapic_ids = numaq_setup_ioapic_ids, |
261 | .update_genapic = numaq_update_genapic, | 281 | .update_genapic = numaq_update_genapic, |
262 | }; | 282 | }; |
263 | 283 | ||
264 | void numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) | 284 | void numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) |
@@ -275,6 +295,7 @@ static __init void early_check_numaq(void) | |||
275 | * Find possible boot-time SMP configuration: | 295 | * Find possible boot-time SMP configuration: |
276 | */ | 296 | */ |
277 | early_find_smp_config(); | 297 | early_find_smp_config(); |
298 | |||
278 | /* | 299 | /* |
279 | * get boot-time SMP configuration: | 300 | * get boot-time SMP configuration: |
280 | */ | 301 | */ |
@@ -291,28 +312,10 @@ int __init get_memcfg_numaq(void) | |||
291 | if (!found_numaq) | 312 | if (!found_numaq) |
292 | return 0; | 313 | return 0; |
293 | smp_dump_qct(); | 314 | smp_dump_qct(); |
315 | |||
294 | return 1; | 316 | return 1; |
295 | } | 317 | } |
296 | 318 | ||
297 | /* | ||
298 | * APIC driver for the IBM NUMAQ chipset. | ||
299 | */ | ||
300 | #include <linux/threads.h> | ||
301 | #include <linux/cpumask.h> | ||
302 | #include <asm/mpspec.h> | ||
303 | #include <asm/fixmap.h> | ||
304 | #include <asm/apicdef.h> | ||
305 | #include <asm/ipi.h> | ||
306 | #include <linux/kernel.h> | ||
307 | #include <linux/string.h> | ||
308 | #include <linux/init.h> | ||
309 | #include <linux/numa.h> | ||
310 | #include <linux/smp.h> | ||
311 | #include <asm/numaq.h> | ||
312 | #include <asm/io.h> | ||
313 | #include <linux/mmzone.h> | ||
314 | #include <linux/nodemask.h> | ||
315 | |||
316 | #define NUMAQ_APIC_DFR_VALUE (APIC_DFR_CLUSTER) | 319 | #define NUMAQ_APIC_DFR_VALUE (APIC_DFR_CLUSTER) |
317 | 320 | ||
318 | static inline unsigned int numaq_get_apic_id(unsigned long x) | 321 | static inline unsigned int numaq_get_apic_id(unsigned long x) |
@@ -337,8 +340,8 @@ static inline void numaq_send_IPI_all(int vector) | |||
337 | 340 | ||
338 | extern void numaq_mps_oem_check(struct mpc_table *, char *, char *); | 341 | extern void numaq_mps_oem_check(struct mpc_table *, char *, char *); |
339 | 342 | ||
340 | #define NUMAQ_TRAMPOLINE_PHYS_LOW (0x8) | 343 | #define NUMAQ_TRAMPOLINE_PHYS_LOW (0x8) |
341 | #define NUMAQ_TRAMPOLINE_PHYS_HIGH (0xa) | 344 | #define NUMAQ_TRAMPOLINE_PHYS_HIGH (0xa) |
342 | 345 | ||
343 | /* | 346 | /* |
344 | * Because we use NMIs rather than the INIT-STARTUP sequence to | 347 | * Because we use NMIs rather than the INIT-STARTUP sequence to |
@@ -426,7 +429,7 @@ static inline int numaq_cpu_present_to_apicid(int mps_cpu) | |||
426 | return BAD_APICID; | 429 | return BAD_APICID; |
427 | } | 430 | } |
428 | 431 | ||
429 | static inline int numaq_apicid_to_node(int logical_apicid) | 432 | static inline int numaq_apicid_to_node(int logical_apicid) |
430 | { | 433 | { |
431 | return logical_apicid >> 4; | 434 | return logical_apicid >> 4; |
432 | } | 435 | } |
@@ -468,7 +471,9 @@ static inline int numaq_phys_pkg_id(int cpuid_apic, int index_msb) | |||
468 | { | 471 | { |
469 | return cpuid_apic >> index_msb; | 472 | return cpuid_apic >> index_msb; |
470 | } | 473 | } |
471 | static int __numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) | 474 | |
475 | static int | ||
476 | __numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) | ||
472 | { | 477 | { |
473 | numaq_mps_oem_check(mpc, oem, productid); | 478 | numaq_mps_oem_check(mpc, oem, productid); |
474 | return found_numaq; | 479 | return found_numaq; |