aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/setup-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/setup-common.c')
-rw-r--r--arch/powerpc/kernel/setup-common.c78
1 files changed, 65 insertions, 13 deletions
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 2de00f870edc..6adb5a1e98bb 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -33,6 +33,7 @@
33#include <linux/serial.h> 33#include <linux/serial.h>
34#include <linux/serial_8250.h> 34#include <linux/serial_8250.h>
35#include <linux/debugfs.h> 35#include <linux/debugfs.h>
36#include <linux/percpu.h>
36#include <asm/io.h> 37#include <asm/io.h>
37#include <asm/prom.h> 38#include <asm/prom.h>
38#include <asm/processor.h> 39#include <asm/processor.h>
@@ -57,6 +58,7 @@
57#include <asm/mmu.h> 58#include <asm/mmu.h>
58#include <asm/lmb.h> 59#include <asm/lmb.h>
59#include <asm/xmon.h> 60#include <asm/xmon.h>
61#include <asm/cputhreads.h>
60 62
61#include "setup.h" 63#include "setup.h"
62 64
@@ -327,6 +329,31 @@ void __init check_for_initrd(void)
327 329
328#ifdef CONFIG_SMP 330#ifdef CONFIG_SMP
329 331
332int threads_per_core, threads_shift;
333cpumask_t threads_core_mask;
334
335static void __init cpu_init_thread_core_maps(int tpc)
336{
337 int i;
338
339 threads_per_core = tpc;
340 threads_core_mask = CPU_MASK_NONE;
341
342 /* This implementation only supports power of 2 number of threads
343 * for simplicity and performance
344 */
345 threads_shift = ilog2(tpc);
346 BUG_ON(tpc != (1 << threads_shift));
347
348 for (i = 0; i < tpc; i++)
349 cpu_set(i, threads_core_mask);
350
351 printk(KERN_INFO "CPU maps initialized for %d thread%s per core\n",
352 tpc, tpc > 1 ? "s" : "");
353 printk(KERN_DEBUG " (thread shift is %d)\n", threads_shift);
354}
355
356
330/** 357/**
331 * setup_cpu_maps - initialize the following cpu maps: 358 * setup_cpu_maps - initialize the following cpu maps:
332 * cpu_possible_map 359 * cpu_possible_map
@@ -350,22 +377,32 @@ void __init smp_setup_cpu_maps(void)
350{ 377{
351 struct device_node *dn = NULL; 378 struct device_node *dn = NULL;
352 int cpu = 0; 379 int cpu = 0;
380 int nthreads = 1;
381
382 DBG("smp_setup_cpu_maps()\n");
353 383
354 while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) { 384 while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
355 const int *intserv; 385 const int *intserv;
356 int j, len = sizeof(u32), nthreads = 1; 386 int j, len;
387
388 DBG(" * %s...\n", dn->full_name);
357 389
358 intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", 390 intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s",
359 &len); 391 &len);
360 if (intserv) 392 if (intserv) {
361 nthreads = len / sizeof(int); 393 nthreads = len / sizeof(int);
362 else { 394 DBG(" ibm,ppc-interrupt-server#s -> %d threads\n",
395 nthreads);
396 } else {
397 DBG(" no ibm,ppc-interrupt-server#s -> 1 thread\n");
363 intserv = of_get_property(dn, "reg", NULL); 398 intserv = of_get_property(dn, "reg", NULL);
364 if (!intserv) 399 if (!intserv)
365 intserv = &cpu; /* assume logical == phys */ 400 intserv = &cpu; /* assume logical == phys */
366 } 401 }
367 402
368 for (j = 0; j < nthreads && cpu < NR_CPUS; j++) { 403 for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
404 DBG(" thread %d -> cpu %d (hard id %d)\n",
405 j, cpu, intserv[j]);
369 cpu_set(cpu, cpu_present_map); 406 cpu_set(cpu, cpu_present_map);
370 set_hard_smp_processor_id(cpu, intserv[j]); 407 set_hard_smp_processor_id(cpu, intserv[j]);
371 cpu_set(cpu, cpu_possible_map); 408 cpu_set(cpu, cpu_possible_map);
@@ -373,6 +410,12 @@ void __init smp_setup_cpu_maps(void)
373 } 410 }
374 } 411 }
375 412
413 /* If no SMT supported, nthreads is forced to 1 */
414 if (!cpu_has_feature(CPU_FTR_SMT)) {
415 DBG(" SMT disabled ! nthreads forced to 1\n");
416 nthreads = 1;
417 }
418
376#ifdef CONFIG_PPC64 419#ifdef CONFIG_PPC64
377 /* 420 /*
378 * On pSeries LPAR, we need to know how many cpus 421 * On pSeries LPAR, we need to know how many cpus
@@ -395,7 +438,7 @@ void __init smp_setup_cpu_maps(void)
395 438
396 /* Double maxcpus for processors which have SMT capability */ 439 /* Double maxcpus for processors which have SMT capability */
397 if (cpu_has_feature(CPU_FTR_SMT)) 440 if (cpu_has_feature(CPU_FTR_SMT))
398 maxcpus *= 2; 441 maxcpus *= nthreads;
399 442
400 if (maxcpus > NR_CPUS) { 443 if (maxcpus > NR_CPUS) {
401 printk(KERN_WARNING 444 printk(KERN_WARNING
@@ -412,9 +455,16 @@ void __init smp_setup_cpu_maps(void)
412 out: 455 out:
413 of_node_put(dn); 456 of_node_put(dn);
414 } 457 }
415
416 vdso_data->processorCount = num_present_cpus(); 458 vdso_data->processorCount = num_present_cpus();
417#endif /* CONFIG_PPC64 */ 459#endif /* CONFIG_PPC64 */
460
461 /* Initialize CPU <=> thread mapping/
462 *
463 * WARNING: We assume that the number of threads is the same for
464 * every CPU in the system. If that is not the case, then some code
465 * here will have to be reworked
466 */
467 cpu_init_thread_core_maps(nthreads);
418} 468}
419 469
420/* 470/*
@@ -424,17 +474,19 @@ void __init smp_setup_cpu_maps(void)
424 */ 474 */
425void __init smp_setup_cpu_sibling_map(void) 475void __init smp_setup_cpu_sibling_map(void)
426{ 476{
427#if defined(CONFIG_PPC64) 477#ifdef CONFIG_PPC64
428 int cpu; 478 int i, cpu, base;
429 479
430 /*
431 * Do the sibling map; assume only two threads per processor.
432 */
433 for_each_possible_cpu(cpu) { 480 for_each_possible_cpu(cpu) {
434 cpu_set(cpu, per_cpu(cpu_sibling_map, cpu)); 481 DBG("Sibling map for CPU %d:", cpu);
435 if (cpu_has_feature(CPU_FTR_SMT)) 482 base = cpu_first_thread_in_core(cpu);
436 cpu_set(cpu ^ 0x1, per_cpu(cpu_sibling_map, cpu)); 483 for (i = 0; i < threads_per_core; i++) {
484 cpu_set(base + i, per_cpu(cpu_sibling_map, cpu));
485 DBG(" %d", base + i);
486 }
487 DBG("\n");
437 } 488 }
489
438#endif /* CONFIG_PPC64 */ 490#endif /* CONFIG_PPC64 */
439} 491}
440#endif /* CONFIG_SMP */ 492#endif /* CONFIG_SMP */