diff options
-rw-r--r-- | arch/powerpc/include/asm/prom.h | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom.c | 57 | ||||
-rw-r--r-- | drivers/of/base.c | 95 | ||||
-rw-r--r-- | include/linux/cpu.h | 1 | ||||
-rw-r--r-- | include/linux/of.h | 7 |
5 files changed, 103 insertions, 60 deletions
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h index bc2da154f68b..ac204e022922 100644 --- a/arch/powerpc/include/asm/prom.h +++ b/arch/powerpc/include/asm/prom.h | |||
@@ -43,9 +43,6 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, | |||
43 | 43 | ||
44 | extern void kdump_move_device_tree(void); | 44 | extern void kdump_move_device_tree(void); |
45 | 45 | ||
46 | /* CPU OF node matching */ | ||
47 | struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); | ||
48 | |||
49 | /* cache lookup */ | 46 | /* cache lookup */ |
50 | struct device_node *of_find_next_cache_node(struct device_node *np); | 47 | struct device_node *of_find_next_cache_node(struct device_node *np); |
51 | 48 | ||
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index f7b8c0be982e..1c14cd4a5e05 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -870,63 +870,6 @@ bool arch_match_cpu_phys_id(int cpu, u64 phys_id) | |||
870 | return (int)phys_id == get_hard_smp_processor_id(cpu); | 870 | return (int)phys_id == get_hard_smp_processor_id(cpu); |
871 | } | 871 | } |
872 | 872 | ||
873 | static bool __of_find_n_match_cpu_property(struct device_node *cpun, | ||
874 | const char *prop_name, int cpu, unsigned int *thread) | ||
875 | { | ||
876 | const __be32 *cell; | ||
877 | int ac, prop_len, tid; | ||
878 | u64 hwid; | ||
879 | |||
880 | ac = of_n_addr_cells(cpun); | ||
881 | cell = of_get_property(cpun, prop_name, &prop_len); | ||
882 | if (!cell) | ||
883 | return false; | ||
884 | prop_len /= sizeof(*cell); | ||
885 | for (tid = 0; tid < prop_len; tid++) { | ||
886 | hwid = of_read_number(cell, ac); | ||
887 | if (arch_match_cpu_phys_id(cpu, hwid)) { | ||
888 | if (thread) | ||
889 | *thread = tid; | ||
890 | return true; | ||
891 | } | ||
892 | cell += ac; | ||
893 | } | ||
894 | return false; | ||
895 | } | ||
896 | |||
897 | /* Find the device node for a given logical cpu number, also returns the cpu | ||
898 | * local thread number (index in ibm,interrupt-server#s) if relevant and | ||
899 | * asked for (non NULL) | ||
900 | */ | ||
901 | struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) | ||
902 | { | ||
903 | struct device_node *cpun, *cpus; | ||
904 | |||
905 | cpus = of_find_node_by_path("/cpus"); | ||
906 | if (!cpus) { | ||
907 | pr_warn("Missing cpus node, bailing out\n"); | ||
908 | return NULL; | ||
909 | } | ||
910 | |||
911 | for_each_child_of_node(cpus, cpun) { | ||
912 | if (of_node_cmp(cpun->type, "cpu")) | ||
913 | continue; | ||
914 | |||
915 | /* Check for non-standard "ibm,ppc-interrupt-server#s" property | ||
916 | * for thread ids on PowerPC. If it doesn't exist fallback to | ||
917 | * standard "reg" property. | ||
918 | */ | ||
919 | if (__of_find_n_match_cpu_property(cpun, | ||
920 | "ibm,ppc-interrupt-server#s", cpu, thread)) | ||
921 | return cpun; | ||
922 | |||
923 | if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread)) | ||
924 | return cpun; | ||
925 | } | ||
926 | return NULL; | ||
927 | } | ||
928 | EXPORT_SYMBOL(of_get_cpu_node); | ||
929 | |||
930 | #if defined(CONFIG_DEBUG_FS) && defined(DEBUG) | 873 | #if defined(CONFIG_DEBUG_FS) && defined(DEBUG) |
931 | static struct debugfs_blob_wrapper flat_dt_blob; | 874 | static struct debugfs_blob_wrapper flat_dt_blob; |
932 | 875 | ||
diff --git a/drivers/of/base.c b/drivers/of/base.c index 5c5427918eb2..605afa9fbe5e 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * 2 of the License, or (at your option) any later version. | 18 | * 2 of the License, or (at your option) any later version. |
19 | */ | 19 | */ |
20 | #include <linux/ctype.h> | 20 | #include <linux/ctype.h> |
21 | #include <linux/cpu.h> | ||
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
22 | #include <linux/of.h> | 23 | #include <linux/of.h> |
23 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
@@ -230,6 +231,100 @@ const void *of_get_property(const struct device_node *np, const char *name, | |||
230 | } | 231 | } |
231 | EXPORT_SYMBOL(of_get_property); | 232 | EXPORT_SYMBOL(of_get_property); |
232 | 233 | ||
234 | /* | ||
235 | * arch_match_cpu_phys_id - Match the given logical CPU and physical id | ||
236 | * | ||
237 | * @cpu: logical cpu index of a core/thread | ||
238 | * @phys_id: physical identifier of a core/thread | ||
239 | * | ||
240 | * CPU logical to physical index mapping is architecture specific. | ||
241 | * However this __weak function provides a default match of physical | ||
242 | * id to logical cpu index. phys_id provided here is usually values read | ||
243 | * from the device tree which must match the hardware internal registers. | ||
244 | * | ||
245 | * Returns true if the physical identifier and the logical cpu index | ||
246 | * correspond to the same core/thread, false otherwise. | ||
247 | */ | ||
248 | bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id) | ||
249 | { | ||
250 | return (u32)phys_id == cpu; | ||
251 | } | ||
252 | |||
253 | /** | ||
254 | * Checks if the given "prop_name" property holds the physical id of the | ||
255 | * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not | ||
256 | * NULL, local thread number within the core is returned in it. | ||
257 | */ | ||
258 | static bool __of_find_n_match_cpu_property(struct device_node *cpun, | ||
259 | const char *prop_name, int cpu, unsigned int *thread) | ||
260 | { | ||
261 | const __be32 *cell; | ||
262 | int ac, prop_len, tid; | ||
263 | u64 hwid; | ||
264 | |||
265 | ac = of_n_addr_cells(cpun); | ||
266 | cell = of_get_property(cpun, prop_name, &prop_len); | ||
267 | if (!cell) | ||
268 | return false; | ||
269 | prop_len /= sizeof(*cell); | ||
270 | for (tid = 0; tid < prop_len; tid++) { | ||
271 | hwid = of_read_number(cell, ac); | ||
272 | if (arch_match_cpu_phys_id(cpu, hwid)) { | ||
273 | if (thread) | ||
274 | *thread = tid; | ||
275 | return true; | ||
276 | } | ||
277 | cell += ac; | ||
278 | } | ||
279 | return false; | ||
280 | } | ||
281 | |||
282 | /** | ||
283 | * of_get_cpu_node - Get device node associated with the given logical CPU | ||
284 | * | ||
285 | * @cpu: CPU number(logical index) for which device node is required | ||
286 | * @thread: if not NULL, local thread number within the physical core is | ||
287 | * returned | ||
288 | * | ||
289 | * The main purpose of this function is to retrieve the device node for the | ||
290 | * given logical CPU index. It should be used to initialize the of_node in | ||
291 | * cpu device. Once of_node in cpu device is populated, all the further | ||
292 | * references can use that instead. | ||
293 | * | ||
294 | * CPU logical to physical index mapping is architecture specific and is built | ||
295 | * before booting secondary cores. This function uses arch_match_cpu_phys_id | ||
296 | * which can be overridden by architecture specific implementation. | ||
297 | * | ||
298 | * Returns a node pointer for the logical cpu if found, else NULL. | ||
299 | */ | ||
300 | struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) | ||
301 | { | ||
302 | struct device_node *cpun, *cpus; | ||
303 | |||
304 | cpus = of_find_node_by_path("/cpus"); | ||
305 | if (!cpus) { | ||
306 | pr_warn("Missing cpus node, bailing out\n"); | ||
307 | return NULL; | ||
308 | } | ||
309 | |||
310 | for_each_child_of_node(cpus, cpun) { | ||
311 | if (of_node_cmp(cpun->type, "cpu")) | ||
312 | continue; | ||
313 | /* Check for non-standard "ibm,ppc-interrupt-server#s" property | ||
314 | * for thread ids on PowerPC. If it doesn't exist fallback to | ||
315 | * standard "reg" property. | ||
316 | */ | ||
317 | if (IS_ENABLED(CONFIG_PPC) && | ||
318 | __of_find_n_match_cpu_property(cpun, | ||
319 | "ibm,ppc-interrupt-server#s", cpu, thread)) | ||
320 | return cpun; | ||
321 | if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread)) | ||
322 | return cpun; | ||
323 | } | ||
324 | return NULL; | ||
325 | } | ||
326 | EXPORT_SYMBOL(of_get_cpu_node); | ||
327 | |||
233 | /** Checks if the given "compat" string matches one of the strings in | 328 | /** Checks if the given "compat" string matches one of the strings in |
234 | * the device's "compatible" property | 329 | * the device's "compatible" property |
235 | */ | 330 | */ |
diff --git a/include/linux/cpu.h b/include/linux/cpu.h index ab0eade73039..3dfed2b9ae2e 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h | |||
@@ -28,6 +28,7 @@ struct cpu { | |||
28 | extern int register_cpu(struct cpu *cpu, int num); | 28 | extern int register_cpu(struct cpu *cpu, int num); |
29 | extern struct device *get_cpu_device(unsigned cpu); | 29 | extern struct device *get_cpu_device(unsigned cpu); |
30 | extern bool cpu_is_hotpluggable(unsigned cpu); | 30 | extern bool cpu_is_hotpluggable(unsigned cpu); |
31 | extern bool arch_match_cpu_phys_id(int cpu, u64 phys_id); | ||
31 | 32 | ||
32 | extern int cpu_add_dev_attr(struct device_attribute *attr); | 33 | extern int cpu_add_dev_attr(struct device_attribute *attr); |
33 | extern void cpu_remove_dev_attr(struct device_attribute *attr); | 34 | extern void cpu_remove_dev_attr(struct device_attribute *attr); |
diff --git a/include/linux/of.h b/include/linux/of.h index 1fd08ca23106..c0bb2f188048 100644 --- a/include/linux/of.h +++ b/include/linux/of.h | |||
@@ -266,6 +266,7 @@ extern int of_device_is_available(const struct device_node *device); | |||
266 | extern const void *of_get_property(const struct device_node *node, | 266 | extern const void *of_get_property(const struct device_node *node, |
267 | const char *name, | 267 | const char *name, |
268 | int *lenp); | 268 | int *lenp); |
269 | extern struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); | ||
269 | #define for_each_property_of_node(dn, pp) \ | 270 | #define for_each_property_of_node(dn, pp) \ |
270 | for (pp = dn->properties; pp != NULL; pp = pp->next) | 271 | for (pp = dn->properties; pp != NULL; pp = pp->next) |
271 | 272 | ||
@@ -459,6 +460,12 @@ static inline const void *of_get_property(const struct device_node *node, | |||
459 | return NULL; | 460 | return NULL; |
460 | } | 461 | } |
461 | 462 | ||
463 | static inline struct device_node *of_get_cpu_node(int cpu, | ||
464 | unsigned int *thread) | ||
465 | { | ||
466 | return NULL; | ||
467 | } | ||
468 | |||
462 | static inline int of_property_read_u64(const struct device_node *np, | 469 | static inline int of_property_read_u64(const struct device_node *np, |
463 | const char *propname, u64 *out_value) | 470 | const char *propname, u64 *out_value) |
464 | { | 471 | { |