aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/setup-common.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-11-04 18:33:55 -0500
committerPaul Mackerras <paulus@samba.org>2005-11-04 18:33:55 -0500
commit5ad570786158e327a1c5d32dd3d66f26d8de6340 (patch)
tree0b4aafe469c72e5887ed0379d62a0ee390db3160 /arch/powerpc/kernel/setup-common.c
parentc3df69cd854551cf70e9c63aa509c26621084f60 (diff)
powerpc: Merge smp.c and smp.h
This also moves setup_cpu_maps to setup-common.c (calling it smp_setup_cpu_maps) and uses it on both 32-bit and 64-bit. Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/setup-common.c')
-rw-r--r--arch/powerpc/kernel/setup-common.c119
1 files changed, 115 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 14ebe3bc48c3..d43fa8c0e5ac 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -170,12 +170,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
170 } 170 }
171 171
172#ifdef CONFIG_SMP 172#ifdef CONFIG_SMP
173#ifdef CONFIG_PPC64 /* XXX for now */
174 pvr = per_cpu(pvr, cpu_id); 173 pvr = per_cpu(pvr, cpu_id);
175#else 174#else
176 pvr = cpu_data[cpu_id].pvr;
177#endif
178#else
179 pvr = mfspr(SPRN_PVR); 175 pvr = mfspr(SPRN_PVR);
180#endif 176#endif
181 maj = (pvr >> 8) & 0xFF; 177 maj = (pvr >> 8) & 0xFF;
@@ -408,3 +404,118 @@ static int __init set_preferred_console(void)
408} 404}
409console_initcall(set_preferred_console); 405console_initcall(set_preferred_console);
410#endif /* CONFIG_PPC_MULTIPLATFORM */ 406#endif /* CONFIG_PPC_MULTIPLATFORM */
407
408#ifdef CONFIG_SMP
409
410/**
411 * setup_cpu_maps - initialize the following cpu maps:
412 * cpu_possible_map
413 * cpu_present_map
414 * cpu_sibling_map
415 *
416 * Having the possible map set up early allows us to restrict allocations
417 * of things like irqstacks to num_possible_cpus() rather than NR_CPUS.
418 *
419 * We do not initialize the online map here; cpus set their own bits in
420 * cpu_online_map as they come up.
421 *
422 * This function is valid only for Open Firmware systems. finish_device_tree
423 * must be called before using this.
424 *
425 * While we're here, we may as well set the "physical" cpu ids in the paca.
426 */
427void __init smp_setup_cpu_maps(void)
428{
429 struct device_node *dn = NULL;
430 int cpu = 0;
431 int swap_cpuid = 0;
432
433 while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
434 int *intserv;
435 int j, len = sizeof(u32), nthreads = 1;
436
437 intserv = (int *)get_property(dn, "ibm,ppc-interrupt-server#s",
438 &len);
439 if (intserv)
440 nthreads = len / sizeof(int);
441 else {
442 intserv = (int *) get_property(dn, "reg", NULL);
443 if (!intserv)
444 intserv = &cpu; /* assume logical == phys */
445 }
446
447 for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
448 cpu_set(cpu, cpu_present_map);
449 set_hard_smp_processor_id(cpu, intserv[j]);
450
451 if (intserv[j] == boot_cpuid_phys)
452 swap_cpuid = cpu;
453 cpu_set(cpu, cpu_possible_map);
454 cpu++;
455 }
456 }
457
458 /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that
459 * boot cpu is logical 0.
460 */
461 if (boot_cpuid_phys != get_hard_smp_processor_id(0)) {
462 u32 tmp;
463 tmp = get_hard_smp_processor_id(0);
464 set_hard_smp_processor_id(0, boot_cpuid_phys);
465 set_hard_smp_processor_id(swap_cpuid, tmp);
466 }
467
468#ifdef CONFIG_PPC64
469 /*
470 * On pSeries LPAR, we need to know how many cpus
471 * could possibly be added to this partition.
472 */
473 if (systemcfg->platform == PLATFORM_PSERIES_LPAR &&
474 (dn = of_find_node_by_path("/rtas"))) {
475 int num_addr_cell, num_size_cell, maxcpus;
476 unsigned int *ireg;
477
478 num_addr_cell = prom_n_addr_cells(dn);
479 num_size_cell = prom_n_size_cells(dn);
480
481 ireg = (unsigned int *)
482 get_property(dn, "ibm,lrdr-capacity", NULL);
483
484 if (!ireg)
485 goto out;
486
487 maxcpus = ireg[num_addr_cell + num_size_cell];
488
489 /* Double maxcpus for processors which have SMT capability */
490 if (cpu_has_feature(CPU_FTR_SMT))
491 maxcpus *= 2;
492
493 if (maxcpus > NR_CPUS) {
494 printk(KERN_WARNING
495 "Partition configured for %d cpus, "
496 "operating system maximum is %d.\n",
497 maxcpus, NR_CPUS);
498 maxcpus = NR_CPUS;
499 } else
500 printk(KERN_INFO "Partition configured for %d cpus.\n",
501 maxcpus);
502
503 for (cpu = 0; cpu < maxcpus; cpu++)
504 cpu_set(cpu, cpu_possible_map);
505 out:
506 of_node_put(dn);
507 }
508
509 /*
510 * Do the sibling map; assume only two threads per processor.
511 */
512 for_each_cpu(cpu) {
513 cpu_set(cpu, cpu_sibling_map[cpu]);
514 if (cpu_has_feature(CPU_FTR_SMT))
515 cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
516 }
517
518 systemcfg->processorCount = num_present_cpus();
519#endif /* CONFIG_PPC64 */
520}
521#endif /* CONFIG_SMP */