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 15328500de6..a4ea08a9ac9 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; |
