of: move of_get_cpu_node implementation to DT core library
authorSudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
Thu, 15 Aug 2013 13:01:40 +0000 (14:01 +0100)
committerSudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
Wed, 21 Aug 2013 09:24:44 +0000 (10:24 +0100)
This patch moves the generalized implementation of of_get_cpu_node from
PowerPC to DT core library, thereby adding support for retrieving cpu
node for a given logical cpu index on any architecture.

The CPU subsystem can now use this function to assign of_node in the
cpu device while registering CPUs.

It is recommended to use these helper function only in pre-SMP/early
initialisation stages to retrieve CPU device node pointers in logical
ordering. Once the cpu devices are registered, it can be retrieved easily
from cpu device of_node which avoids unnecessary parsing and matching.

Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Grant Likely <grant.likely@linaro.org>
Acked-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
arch/powerpc/include/asm/prom.h
arch/powerpc/kernel/prom.c
drivers/of/base.c
include/linux/cpu.h
include/linux/of.h

index bc2da154f68be579d19e81e5789073e436ac838b..ac204e0229220bd15cd1dfb550e355eed3020962 100644 (file)
@@ -43,9 +43,6 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
 
 extern void kdump_move_device_tree(void);
 
-/* CPU OF node matching */
-struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
-
 /* cache lookup */
 struct device_node *of_find_next_cache_node(struct device_node *np);
 
index f7b8c0be982ec199bc4cd5e4d26ece282512b905..1c14cd4a5e05972bf45fc31a5535aa97df96f025 100644 (file)
@@ -870,63 +870,6 @@ bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
        return (int)phys_id == get_hard_smp_processor_id(cpu);
 }
 
-static bool __of_find_n_match_cpu_property(struct device_node *cpun,
-                       const char *prop_name, int cpu, unsigned int *thread)
-{
-       const __be32 *cell;
-       int ac, prop_len, tid;
-       u64 hwid;
-
-       ac = of_n_addr_cells(cpun);
-       cell = of_get_property(cpun, prop_name, &prop_len);
-       if (!cell)
-               return false;
-       prop_len /= sizeof(*cell);
-       for (tid = 0; tid < prop_len; tid++) {
-               hwid = of_read_number(cell, ac);
-               if (arch_match_cpu_phys_id(cpu, hwid)) {
-                       if (thread)
-                               *thread = tid;
-                       return true;
-               }
-               cell += ac;
-       }
-       return false;
-}
-
-/* Find the device node for a given logical cpu number, also returns the cpu
- * local thread number (index in ibm,interrupt-server#s) if relevant and
- * asked for (non NULL)
- */
-struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
-{
-       struct device_node *cpun, *cpus;
-
-       cpus = of_find_node_by_path("/cpus");
-       if (!cpus) {
-               pr_warn("Missing cpus node, bailing out\n");
-               return NULL;
-       }
-
-       for_each_child_of_node(cpus, cpun) {
-               if (of_node_cmp(cpun->type, "cpu"))
-                       continue;
-
-               /* Check for non-standard "ibm,ppc-interrupt-server#s" property
-                * for thread ids on PowerPC. If it doesn't exist fallback to
-                * standard "reg" property.
-                */
-               if (__of_find_n_match_cpu_property(cpun,
-                               "ibm,ppc-interrupt-server#s", cpu, thread))
-                       return cpun;
-
-               if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread))
-                       return cpun;
-       }
-       return NULL;
-}
-EXPORT_SYMBOL(of_get_cpu_node);
-
 #if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
 static struct debugfs_blob_wrapper flat_dt_blob;
 
index 5c5427918eb2f54b6a22d766aa7e697ca21c7666..605afa9fbe5e089776f04d8c1ae24484fca52384 100644 (file)
@@ -18,6 +18,7 @@
  *      2 of the License, or (at your option) any later version.
  */
 #include <linux/ctype.h>
+#include <linux/cpu.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/spinlock.h>
@@ -230,6 +231,100 @@ const void *of_get_property(const struct device_node *np, const char *name,
 }
 EXPORT_SYMBOL(of_get_property);
 
+/*
+ * arch_match_cpu_phys_id - Match the given logical CPU and physical id
+ *
+ * @cpu: logical cpu index of a core/thread
+ * @phys_id: physical identifier of a core/thread
+ *
+ * CPU logical to physical index mapping is architecture specific.
+ * However this __weak function provides a default match of physical
+ * id to logical cpu index. phys_id provided here is usually values read
+ * from the device tree which must match the hardware internal registers.
+ *
+ * Returns true if the physical identifier and the logical cpu index
+ * correspond to the same core/thread, false otherwise.
+ */
+bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id)
+{
+       return (u32)phys_id == cpu;
+}
+
+/**
+ * Checks if the given "prop_name" property holds the physical id of the
+ * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not
+ * NULL, local thread number within the core is returned in it.
+ */
+static bool __of_find_n_match_cpu_property(struct device_node *cpun,
+                       const char *prop_name, int cpu, unsigned int *thread)
+{
+       const __be32 *cell;
+       int ac, prop_len, tid;
+       u64 hwid;
+
+       ac = of_n_addr_cells(cpun);
+       cell = of_get_property(cpun, prop_name, &prop_len);
+       if (!cell)
+               return false;
+       prop_len /= sizeof(*cell);
+       for (tid = 0; tid < prop_len; tid++) {
+               hwid = of_read_number(cell, ac);
+               if (arch_match_cpu_phys_id(cpu, hwid)) {
+                       if (thread)
+                               *thread = tid;
+                       return true;
+               }
+               cell += ac;
+       }
+       return false;
+}
+
+/**
+ * of_get_cpu_node - Get device node associated with the given logical CPU
+ *
+ * @cpu: CPU number(logical index) for which device node is required
+ * @thread: if not NULL, local thread number within the physical core is
+ *          returned
+ *
+ * The main purpose of this function is to retrieve the device node for the
+ * given logical CPU index. It should be used to initialize the of_node in
+ * cpu device. Once of_node in cpu device is populated, all the further
+ * references can use that instead.
+ *
+ * CPU logical to physical index mapping is architecture specific and is built
+ * before booting secondary cores. This function uses arch_match_cpu_phys_id
+ * which can be overridden by architecture specific implementation.
+ *
+ * Returns a node pointer for the logical cpu if found, else NULL.
+ */
+struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
+{
+       struct device_node *cpun, *cpus;
+
+       cpus = of_find_node_by_path("/cpus");
+       if (!cpus) {
+               pr_warn("Missing cpus node, bailing out\n");
+               return NULL;
+       }
+
+       for_each_child_of_node(cpus, cpun) {
+               if (of_node_cmp(cpun->type, "cpu"))
+                       continue;
+               /* Check for non-standard "ibm,ppc-interrupt-server#s" property
+                * for thread ids on PowerPC. If it doesn't exist fallback to
+                * standard "reg" property.
+                */
+               if (IS_ENABLED(CONFIG_PPC) &&
+                       __of_find_n_match_cpu_property(cpun,
+                               "ibm,ppc-interrupt-server#s", cpu, thread))
+                       return cpun;
+               if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread))
+                       return cpun;
+       }
+       return NULL;
+}
+EXPORT_SYMBOL(of_get_cpu_node);
+
 /** Checks if the given "compat" string matches one of the strings in
  * the device's "compatible" property
  */
index ab0eade730392265b298833bd9db4579f387d1bb..3dfed2b9ae2e73ac672993f207bda6b2cbe4add8 100644 (file)
@@ -28,6 +28,7 @@ struct cpu {
 extern int register_cpu(struct cpu *cpu, int num);
 extern struct device *get_cpu_device(unsigned cpu);
 extern bool cpu_is_hotpluggable(unsigned cpu);
+extern bool arch_match_cpu_phys_id(int cpu, u64 phys_id);
 
 extern int cpu_add_dev_attr(struct device_attribute *attr);
 extern void cpu_remove_dev_attr(struct device_attribute *attr);
index 1fd08ca23106df836678989d96e2a16824b1a932..c0bb2f188048b21df8a401de13644a3de3c8e22d 100644 (file)
@@ -266,6 +266,7 @@ extern int of_device_is_available(const struct device_node *device);
 extern const void *of_get_property(const struct device_node *node,
                                const char *name,
                                int *lenp);
+extern struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
 #define for_each_property_of_node(dn, pp) \
        for (pp = dn->properties; pp != NULL; pp = pp->next)
 
@@ -459,6 +460,12 @@ static inline const void *of_get_property(const struct device_node *node,
        return NULL;
 }
 
+static inline struct device_node *of_get_cpu_node(int cpu,
+                                       unsigned int *thread)
+{
+       return NULL;
+}
+
 static inline int of_property_read_u64(const struct device_node *np,
                                       const char *propname, u64 *out_value)
 {