sparc64: Refactor OBP cpu scanning code using an iterator.
authorDavid S. Miller <davem@davemloft.net>
Wed, 27 May 2009 04:46:14 +0000 (21:46 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 16 Jun 2009 11:56:16 +0000 (04:56 -0700)
With feedback from Sam Ravnborg.

Signed-off-by: David S. Miller <davem@davemloft.net>
arch/sparc/include/asm/prom.h
arch/sparc/kernel/prom_64.c

index 900d447..1b15212 100644 (file)
@@ -86,6 +86,7 @@ extern int of_node_to_nid(struct device_node *dp);
 #endif
 
 extern void prom_build_devicetree(void);
+extern void of_populate_present_mask(void);
 
 /* Dummy ref counting routines - to be implemented later */
 static inline struct device_node *of_node_get(struct device_node *node)
index ca55c70..4d92f48 100644 (file)
@@ -374,75 +374,26 @@ static const char *get_mid_prop(void)
        return (tlb_type == spitfire ? "upa-portid" : "portid");
 }
 
-struct device_node *of_find_node_by_cpuid(int cpuid)
-{
-       struct device_node *dp;
-       const char *mid_prop = get_mid_prop();
-
-       for_each_node_by_type(dp, "cpu") {
-               int id = of_getintprop_default(dp, mid_prop, -1);
-               const char *this_mid_prop = mid_prop;
-
-               if (id < 0) {
-                       this_mid_prop = "cpuid";
-                       id = of_getintprop_default(dp, this_mid_prop, -1);
-               }
-
-               if (id < 0) {
-                       prom_printf("OF: Serious problem, cpu lacks "
-                                   "%s property", this_mid_prop);
-                       prom_halt();
-               }
-               if (cpuid == id)
-                       return dp;
-       }
-       return NULL;
-}
-
-void __init of_fill_in_cpu_data(void)
+static void *of_iterate_over_cpus(void *(*func)(struct device_node *, int, int), int arg)
 {
        struct device_node *dp;
        const char *mid_prop;
 
-       if (tlb_type == hypervisor)
-               return;
-
        mid_prop = get_mid_prop();
-       ncpus_probed = 0;
        for_each_node_by_type(dp, "cpu") {
                int cpuid = of_getintprop_default(dp, mid_prop, -1);
                const char *this_mid_prop = mid_prop;
-               struct device_node *portid_parent;
-               int portid = -1;
+               void *ret;
 
-               portid_parent = NULL;
                if (cpuid < 0) {
                        this_mid_prop = "cpuid";
                        cpuid = of_getintprop_default(dp, this_mid_prop, -1);
-                       if (cpuid >= 0) {
-                               int limit = 2;
-
-                               portid_parent = dp;
-                               while (limit--) {
-                                       portid_parent = portid_parent->parent;
-                                       if (!portid_parent)
-                                               break;
-                                       portid = of_getintprop_default(portid_parent,
-                                                                      "portid", -1);
-                                       if (portid >= 0)
-                                               break;
-                               }
-                       }
                }
-
                if (cpuid < 0) {
                        prom_printf("OF: Serious problem, cpu lacks "
                                    "%s property", this_mid_prop);
                        prom_halt();
                }
-
-               ncpus_probed++;
-
 #ifdef CONFIG_SMP
                if (cpuid >= NR_CPUS) {
                        printk(KERN_WARNING "Ignoring CPU %d which is "
@@ -450,79 +401,143 @@ void __init of_fill_in_cpu_data(void)
                               cpuid, NR_CPUS);
                        continue;
                }
-#else
-               /* On uniprocessor we only want the values for the
-                * real physical cpu the kernel booted onto, however
-                * cpu_data() only has one entry at index 0.
-                */
-               if (cpuid != real_hard_smp_processor_id())
-                       continue;
-               cpuid = 0;
 #endif
+               ret = func(dp, cpuid, arg);
+               if (ret)
+                       return ret;
+       }
+       return NULL;
+}
 
-               cpu_data(cpuid).clock_tick =
-                       of_getintprop_default(dp, "clock-frequency", 0);
-
-               if (portid_parent) {
-                       cpu_data(cpuid).dcache_size =
-                               of_getintprop_default(dp, "l1-dcache-size",
-                                                     16 * 1024);
-                       cpu_data(cpuid).dcache_line_size =
-                               of_getintprop_default(dp, "l1-dcache-line-size",
-                                                     32);
-                       cpu_data(cpuid).icache_size =
-                               of_getintprop_default(dp, "l1-icache-size",
-                                                     8 * 1024);
-                       cpu_data(cpuid).icache_line_size =
-                               of_getintprop_default(dp, "l1-icache-line-size",
-                                                     32);
-                       cpu_data(cpuid).ecache_size =
-                               of_getintprop_default(dp, "l2-cache-size", 0);
-                       cpu_data(cpuid).ecache_line_size =
-                               of_getintprop_default(dp, "l2-cache-line-size", 0);
-                       if (!cpu_data(cpuid).ecache_size ||
-                           !cpu_data(cpuid).ecache_line_size) {
-                               cpu_data(cpuid).ecache_size =
-                                       of_getintprop_default(portid_parent,
-                                                             "l2-cache-size",
-                                                             (4 * 1024 * 1024));
-                               cpu_data(cpuid).ecache_line_size =
-                                       of_getintprop_default(portid_parent,
-                                                             "l2-cache-line-size", 64);
-                       }
-
-                       cpu_data(cpuid).core_id = portid + 1;
-                       cpu_data(cpuid).proc_id = portid;
+static void *check_cpu_node(struct device_node *dp, int cpuid, int id)
+{
+       if (id == cpuid)
+               return dp;
+       return NULL;
+}
+
+struct device_node *of_find_node_by_cpuid(int cpuid)
+{
+       return of_iterate_over_cpus(check_cpu_node, cpuid);
+}
+
+static void *record_one_cpu(struct device_node *dp, int cpuid, int arg)
+{
+       ncpus_probed++;
 #ifdef CONFIG_SMP
-                       sparc64_multi_core = 1;
+       set_cpu_present(cpuid, true);
+       set_cpu_possible(cpuid, true);
 #endif
-               } else {
-                       cpu_data(cpuid).dcache_size =
-                               of_getintprop_default(dp, "dcache-size", 16 * 1024);
-                       cpu_data(cpuid).dcache_line_size =
-                               of_getintprop_default(dp, "dcache-line-size", 32);
+       return NULL;
+}
 
-                       cpu_data(cpuid).icache_size =
-                               of_getintprop_default(dp, "icache-size", 16 * 1024);
-                       cpu_data(cpuid).icache_line_size =
-                               of_getintprop_default(dp, "icache-line-size", 32);
+void __init of_populate_present_mask(void)
+{
+       if (tlb_type == hypervisor)
+               return;
+
+       ncpus_probed = 0;
+       of_iterate_over_cpus(record_one_cpu, 0);
+}
 
+static void *fill_in_one_cpu(struct device_node *dp, int cpuid, int arg)
+{
+       struct device_node *portid_parent = NULL;
+       int portid = -1;
+
+       if (of_find_property(dp, "cpuid", NULL)) {
+               int limit = 2;
+
+               portid_parent = dp;
+               while (limit--) {
+                       portid_parent = portid_parent->parent;
+                       if (!portid_parent)
+                               break;
+                       portid = of_getintprop_default(portid_parent,
+                                                      "portid", -1);
+                       if (portid >= 0)
+                               break;
+               }
+       }
+
+#ifndef CONFIG_SMP
+       /* On uniprocessor we only want the values for the
+        * real physical cpu the kernel booted onto, however
+        * cpu_data() only has one entry at index 0.
+        */
+       if (cpuid != real_hard_smp_processor_id())
+               return NULL;
+       cpuid = 0;
+#endif
+
+       cpu_data(cpuid).clock_tick =
+               of_getintprop_default(dp, "clock-frequency", 0);
+
+       if (portid_parent) {
+               cpu_data(cpuid).dcache_size =
+                       of_getintprop_default(dp, "l1-dcache-size",
+                                             16 * 1024);
+               cpu_data(cpuid).dcache_line_size =
+                       of_getintprop_default(dp, "l1-dcache-line-size",
+                                             32);
+               cpu_data(cpuid).icache_size =
+                       of_getintprop_default(dp, "l1-icache-size",
+                                             8 * 1024);
+               cpu_data(cpuid).icache_line_size =
+                       of_getintprop_default(dp, "l1-icache-line-size",
+                                             32);
+               cpu_data(cpuid).ecache_size =
+                       of_getintprop_default(dp, "l2-cache-size", 0);
+               cpu_data(cpuid).ecache_line_size =
+                       of_getintprop_default(dp, "l2-cache-line-size", 0);
+               if (!cpu_data(cpuid).ecache_size ||
+                   !cpu_data(cpuid).ecache_line_size) {
                        cpu_data(cpuid).ecache_size =
-                               of_getintprop_default(dp, "ecache-size",
+                               of_getintprop_default(portid_parent,
+                                                     "l2-cache-size",
                                                      (4 * 1024 * 1024));
                        cpu_data(cpuid).ecache_line_size =
-                               of_getintprop_default(dp, "ecache-line-size", 64);
-
-                       cpu_data(cpuid).core_id = 0;
-                       cpu_data(cpuid).proc_id = -1;
+                               of_getintprop_default(portid_parent,
+                                                     "l2-cache-line-size", 64);
                }
 
+               cpu_data(cpuid).core_id = portid + 1;
+               cpu_data(cpuid).proc_id = portid;
 #ifdef CONFIG_SMP
-               set_cpu_present(cpuid, true);
-               set_cpu_possible(cpuid, true);
+               sparc64_multi_core = 1;
 #endif
+       } else {
+               cpu_data(cpuid).dcache_size =
+                       of_getintprop_default(dp, "dcache-size", 16 * 1024);
+               cpu_data(cpuid).dcache_line_size =
+                       of_getintprop_default(dp, "dcache-line-size", 32);
+
+               cpu_data(cpuid).icache_size =
+                       of_getintprop_default(dp, "icache-size", 16 * 1024);
+               cpu_data(cpuid).icache_line_size =
+                       of_getintprop_default(dp, "icache-line-size", 32);
+
+               cpu_data(cpuid).ecache_size =
+                       of_getintprop_default(dp, "ecache-size",
+                                             (4 * 1024 * 1024));
+               cpu_data(cpuid).ecache_line_size =
+                       of_getintprop_default(dp, "ecache-line-size", 64);
+
+               cpu_data(cpuid).core_id = 0;
+               cpu_data(cpuid).proc_id = -1;
        }
 
+       return NULL;
+}
+
+void __init of_fill_in_cpu_data(void)
+{
+       if (tlb_type == hypervisor)
+               return;
+
+       of_populate_present_mask();
+       of_iterate_over_cpus(fill_in_one_cpu, 0);
+
        smp_fill_in_sib_core_maps();
 }