diff options
author | David Miller <davem@davemloft.net> | 2013-10-03 17:24:51 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@linaro.org> | 2013-10-15 15:09:10 -0400 |
commit | d1cb9d1af0bc11b7450a6032f43935c746609418 (patch) | |
tree | 061b56dbd9e656730262445b373bacd399c0678e | |
parent | 444c91e5720cb5b825356e32c67c2c5184d1c09a (diff) |
of: Make cpu node handling more portable.
Use for_each_node_by_type() to iterate all cpu nodes in the
system.
Provide and overridable function arch_find_n_match_cpu_physical_id,
which sees if the given device node matches 'cpu' and if so sets
'*thread' when non-NULL to the cpu thread number within the core.
The default implementation behaves the same as the existing code.
Add a sparc64 implementation.
Signed-off-by: David S. Miller <davem@davemloft.net>
Tested-by: Sudeep KarkadaNagesha <Sudeep.KarkadaNagesha@arm.com>
Signed-off-by: Grant Likely <grant.likely@linaro.org>
-rw-r--r-- | arch/sparc/kernel/prom_64.c | 53 | ||||
-rw-r--r-- | drivers/of/base.c | 45 | ||||
-rw-r--r-- | include/linux/cpu.h | 3 |
3 files changed, 84 insertions, 17 deletions
diff --git a/arch/sparc/kernel/prom_64.c b/arch/sparc/kernel/prom_64.c index d397d7fc5c28..6b39125eb927 100644 --- a/arch/sparc/kernel/prom_64.c +++ b/arch/sparc/kernel/prom_64.c | |||
@@ -373,6 +373,59 @@ static const char *get_mid_prop(void) | |||
373 | return (tlb_type == spitfire ? "upa-portid" : "portid"); | 373 | return (tlb_type == spitfire ? "upa-portid" : "portid"); |
374 | } | 374 | } |
375 | 375 | ||
376 | bool arch_find_n_match_cpu_physical_id(struct device_node *cpun, | ||
377 | int cpu, unsigned int *thread) | ||
378 | { | ||
379 | const char *mid_prop = get_mid_prop(); | ||
380 | int this_cpu_id; | ||
381 | |||
382 | /* On hypervisor based platforms we interrogate the 'reg' | ||
383 | * property. On everything else we look for a 'upa-portis', | ||
384 | * 'portid', or 'cpuid' property. | ||
385 | */ | ||
386 | |||
387 | if (tlb_type == hypervisor) { | ||
388 | struct property *prop = of_find_property(cpun, "reg", NULL); | ||
389 | u32 *regs; | ||
390 | |||
391 | if (!prop) { | ||
392 | pr_warn("CPU node missing reg property\n"); | ||
393 | return false; | ||
394 | } | ||
395 | regs = prop->value; | ||
396 | this_cpu_id = regs[0] & 0x0fffffff; | ||
397 | } else { | ||
398 | this_cpu_id = of_getintprop_default(cpun, mid_prop, -1); | ||
399 | |||
400 | if (this_cpu_id < 0) { | ||
401 | mid_prop = "cpuid"; | ||
402 | this_cpu_id = of_getintprop_default(cpun, mid_prop, -1); | ||
403 | } | ||
404 | if (this_cpu_id < 0) { | ||
405 | pr_warn("CPU node missing cpu ID property\n"); | ||
406 | return false; | ||
407 | } | ||
408 | } | ||
409 | if (this_cpu_id == cpu) { | ||
410 | if (thread) { | ||
411 | int proc_id = cpu_data(cpu).proc_id; | ||
412 | |||
413 | /* On sparc64, the cpu thread information is obtained | ||
414 | * either from OBP or the machine description. We've | ||
415 | * actually probed this information already long before | ||
416 | * this interface gets called so instead of interrogating | ||
417 | * both the OF node and the MDESC again, just use what | ||
418 | * we discovered already. | ||
419 | */ | ||
420 | if (proc_id < 0) | ||
421 | proc_id = 0; | ||
422 | *thread = proc_id; | ||
423 | } | ||
424 | return true; | ||
425 | } | ||
426 | return false; | ||
427 | } | ||
428 | |||
376 | static void *of_iterate_over_cpus(void *(*func)(struct device_node *, int, int), int arg) | 429 | static void *of_iterate_over_cpus(void *(*func)(struct device_node *, int, int), int arg) |
377 | { | 430 | { |
378 | struct device_node *dp; | 431 | struct device_node *dp; |
diff --git a/drivers/of/base.c b/drivers/of/base.c index 7d4c70f859e3..e4c99453adf1 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -280,6 +280,31 @@ static bool __of_find_n_match_cpu_property(struct device_node *cpun, | |||
280 | return false; | 280 | return false; |
281 | } | 281 | } |
282 | 282 | ||
283 | /* | ||
284 | * arch_find_n_match_cpu_physical_id - See if the given device node is | ||
285 | * for the cpu corresponding to logical cpu 'cpu'. Return true if so, | ||
286 | * else false. If 'thread' is non-NULL, the local thread number within the | ||
287 | * core is returned in it. | ||
288 | */ | ||
289 | bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, | ||
290 | int cpu, unsigned int *thread) | ||
291 | { | ||
292 | /* Check for non-standard "ibm,ppc-interrupt-server#s" property | ||
293 | * for thread ids on PowerPC. If it doesn't exist fallback to | ||
294 | * standard "reg" property. | ||
295 | */ | ||
296 | if (IS_ENABLED(CONFIG_PPC) && | ||
297 | __of_find_n_match_cpu_property(cpun, | ||
298 | "ibm,ppc-interrupt-server#s", | ||
299 | cpu, thread)) | ||
300 | return true; | ||
301 | |||
302 | if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread)) | ||
303 | return true; | ||
304 | |||
305 | return false; | ||
306 | } | ||
307 | |||
283 | /** | 308 | /** |
284 | * of_get_cpu_node - Get device node associated with the given logical CPU | 309 | * of_get_cpu_node - Get device node associated with the given logical CPU |
285 | * | 310 | * |
@@ -300,24 +325,10 @@ static bool __of_find_n_match_cpu_property(struct device_node *cpun, | |||
300 | */ | 325 | */ |
301 | struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) | 326 | struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) |
302 | { | 327 | { |
303 | struct device_node *cpun, *cpus; | 328 | struct device_node *cpun; |
304 | |||
305 | cpus = of_find_node_by_path("/cpus"); | ||
306 | if (!cpus) | ||
307 | return NULL; | ||
308 | 329 | ||
309 | for_each_child_of_node(cpus, cpun) { | 330 | for_each_node_by_type(cpun, "cpu") { |
310 | if (of_node_cmp(cpun->type, "cpu")) | 331 | if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread)) |
311 | continue; | ||
312 | /* Check for non-standard "ibm,ppc-interrupt-server#s" property | ||
313 | * for thread ids on PowerPC. If it doesn't exist fallback to | ||
314 | * standard "reg" property. | ||
315 | */ | ||
316 | if (IS_ENABLED(CONFIG_PPC) && | ||
317 | __of_find_n_match_cpu_property(cpun, | ||
318 | "ibm,ppc-interrupt-server#s", cpu, thread)) | ||
319 | return cpun; | ||
320 | if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread)) | ||
321 | return cpun; | 332 | return cpun; |
322 | } | 333 | } |
323 | return NULL; | 334 | return NULL; |
diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 801ff9e73679..fbd25c3c2923 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/cpumask.h> | 18 | #include <linux/cpumask.h> |
19 | 19 | ||
20 | struct device; | 20 | struct device; |
21 | struct device_node; | ||
21 | 22 | ||
22 | struct cpu { | 23 | struct cpu { |
23 | int node_id; /* The node which contains the CPU */ | 24 | int node_id; /* The node which contains the CPU */ |
@@ -29,6 +30,8 @@ extern int register_cpu(struct cpu *cpu, int num); | |||
29 | extern struct device *get_cpu_device(unsigned cpu); | 30 | extern struct device *get_cpu_device(unsigned cpu); |
30 | extern bool cpu_is_hotpluggable(unsigned cpu); | 31 | extern bool cpu_is_hotpluggable(unsigned cpu); |
31 | extern bool arch_match_cpu_phys_id(int cpu, u64 phys_id); | 32 | extern bool arch_match_cpu_phys_id(int cpu, u64 phys_id); |
33 | extern bool arch_find_n_match_cpu_physical_id(struct device_node *cpun, | ||
34 | int cpu, unsigned int *thread); | ||
32 | 35 | ||
33 | extern int cpu_add_dev_attr(struct device_attribute *attr); | 36 | extern int cpu_add_dev_attr(struct device_attribute *attr); |
34 | extern void cpu_remove_dev_attr(struct device_attribute *attr); | 37 | extern void cpu_remove_dev_attr(struct device_attribute *attr); |