powerpc: Merge smp.c and smp.h
[deliverable/linux.git] / arch / powerpc / kernel / setup-common.c
index 14ebe3bc48c3e7e5621601180d55e5568f4437f4..d43fa8c0e5ac0861058b8800dafffb7fc63a8a5a 100644 (file)
@@ -170,11 +170,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        }
 
 #ifdef CONFIG_SMP
-#ifdef CONFIG_PPC64    /* XXX for now */
        pvr = per_cpu(pvr, cpu_id);
-#else
-       pvr = cpu_data[cpu_id].pvr;
-#endif
 #else
        pvr = mfspr(SPRN_PVR);
 #endif
@@ -408,3 +404,118 @@ static int __init set_preferred_console(void)
 }
 console_initcall(set_preferred_console);
 #endif /* CONFIG_PPC_MULTIPLATFORM */
+
+#ifdef CONFIG_SMP
+
+/**
+ * setup_cpu_maps - initialize the following cpu maps:
+ *                  cpu_possible_map
+ *                  cpu_present_map
+ *                  cpu_sibling_map
+ *
+ * Having the possible map set up early allows us to restrict allocations
+ * of things like irqstacks to num_possible_cpus() rather than NR_CPUS.
+ *
+ * We do not initialize the online map here; cpus set their own bits in
+ * cpu_online_map as they come up.
+ *
+ * This function is valid only for Open Firmware systems.  finish_device_tree
+ * must be called before using this.
+ *
+ * While we're here, we may as well set the "physical" cpu ids in the paca.
+ */
+void __init smp_setup_cpu_maps(void)
+{
+       struct device_node *dn = NULL;
+       int cpu = 0;
+       int swap_cpuid = 0;
+
+       while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
+               int *intserv;
+               int j, len = sizeof(u32), nthreads = 1;
+
+               intserv = (int *)get_property(dn, "ibm,ppc-interrupt-server#s",
+                                             &len);
+               if (intserv)
+                       nthreads = len / sizeof(int);
+               else {
+                       intserv = (int *) get_property(dn, "reg", NULL);
+                       if (!intserv)
+                               intserv = &cpu; /* assume logical == phys */
+               }
+
+               for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
+                       cpu_set(cpu, cpu_present_map);
+                       set_hard_smp_processor_id(cpu, intserv[j]);
+
+                       if (intserv[j] == boot_cpuid_phys)
+                               swap_cpuid = cpu;
+                       cpu_set(cpu, cpu_possible_map);
+                       cpu++;
+               }
+       }
+
+       /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that
+        * boot cpu is logical 0.
+        */
+       if (boot_cpuid_phys != get_hard_smp_processor_id(0)) {
+               u32 tmp;
+               tmp = get_hard_smp_processor_id(0);
+               set_hard_smp_processor_id(0, boot_cpuid_phys);
+               set_hard_smp_processor_id(swap_cpuid, tmp);
+       }
+
+#ifdef CONFIG_PPC64
+       /*
+        * On pSeries LPAR, we need to know how many cpus
+        * could possibly be added to this partition.
+        */
+       if (systemcfg->platform == PLATFORM_PSERIES_LPAR &&
+                               (dn = of_find_node_by_path("/rtas"))) {
+               int num_addr_cell, num_size_cell, maxcpus;
+               unsigned int *ireg;
+
+               num_addr_cell = prom_n_addr_cells(dn);
+               num_size_cell = prom_n_size_cells(dn);
+
+               ireg = (unsigned int *)
+                       get_property(dn, "ibm,lrdr-capacity", NULL);
+
+               if (!ireg)
+                       goto out;
+
+               maxcpus = ireg[num_addr_cell + num_size_cell];
+
+               /* Double maxcpus for processors which have SMT capability */
+               if (cpu_has_feature(CPU_FTR_SMT))
+                       maxcpus *= 2;
+
+               if (maxcpus > NR_CPUS) {
+                       printk(KERN_WARNING
+                              "Partition configured for %d cpus, "
+                              "operating system maximum is %d.\n",
+                              maxcpus, NR_CPUS);
+                       maxcpus = NR_CPUS;
+               } else
+                       printk(KERN_INFO "Partition configured for %d cpus.\n",
+                              maxcpus);
+
+               for (cpu = 0; cpu < maxcpus; cpu++)
+                       cpu_set(cpu, cpu_possible_map);
+       out:
+               of_node_put(dn);
+       }
+
+       /*
+        * Do the sibling map; assume only two threads per processor.
+        */
+       for_each_cpu(cpu) {
+               cpu_set(cpu, cpu_sibling_map[cpu]);
+               if (cpu_has_feature(CPU_FTR_SMT))
+                       cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
+       }
+
+       systemcfg->processorCount = num_present_cpus();
+#endif /* CONFIG_PPC64 */
+}
+#endif /* CONFIG_SMP */
This page took 0.025797 seconds and 5 git commands to generate.