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>
This commit is contained in:
parent
444c91e572
commit
d1cb9d1af0
3 changed files with 84 additions and 17 deletions
|
@ -373,6 +373,59 @@ static const char *get_mid_prop(void)
|
||||||
return (tlb_type == spitfire ? "upa-portid" : "portid");
|
return (tlb_type == spitfire ? "upa-portid" : "portid");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool arch_find_n_match_cpu_physical_id(struct device_node *cpun,
|
||||||
|
int cpu, unsigned int *thread)
|
||||||
|
{
|
||||||
|
const char *mid_prop = get_mid_prop();
|
||||||
|
int this_cpu_id;
|
||||||
|
|
||||||
|
/* On hypervisor based platforms we interrogate the 'reg'
|
||||||
|
* property. On everything else we look for a 'upa-portis',
|
||||||
|
* 'portid', or 'cpuid' property.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (tlb_type == hypervisor) {
|
||||||
|
struct property *prop = of_find_property(cpun, "reg", NULL);
|
||||||
|
u32 *regs;
|
||||||
|
|
||||||
|
if (!prop) {
|
||||||
|
pr_warn("CPU node missing reg property\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
regs = prop->value;
|
||||||
|
this_cpu_id = regs[0] & 0x0fffffff;
|
||||||
|
} else {
|
||||||
|
this_cpu_id = of_getintprop_default(cpun, mid_prop, -1);
|
||||||
|
|
||||||
|
if (this_cpu_id < 0) {
|
||||||
|
mid_prop = "cpuid";
|
||||||
|
this_cpu_id = of_getintprop_default(cpun, mid_prop, -1);
|
||||||
|
}
|
||||||
|
if (this_cpu_id < 0) {
|
||||||
|
pr_warn("CPU node missing cpu ID property\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this_cpu_id == cpu) {
|
||||||
|
if (thread) {
|
||||||
|
int proc_id = cpu_data(cpu).proc_id;
|
||||||
|
|
||||||
|
/* On sparc64, the cpu thread information is obtained
|
||||||
|
* either from OBP or the machine description. We've
|
||||||
|
* actually probed this information already long before
|
||||||
|
* this interface gets called so instead of interrogating
|
||||||
|
* both the OF node and the MDESC again, just use what
|
||||||
|
* we discovered already.
|
||||||
|
*/
|
||||||
|
if (proc_id < 0)
|
||||||
|
proc_id = 0;
|
||||||
|
*thread = proc_id;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void *of_iterate_over_cpus(void *(*func)(struct device_node *, int, int), int arg)
|
static void *of_iterate_over_cpus(void *(*func)(struct device_node *, int, int), int arg)
|
||||||
{
|
{
|
||||||
struct device_node *dp;
|
struct device_node *dp;
|
||||||
|
|
|
@ -280,6 +280,31 @@ static bool __of_find_n_match_cpu_property(struct device_node *cpun,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* arch_find_n_match_cpu_physical_id - See if the given device node is
|
||||||
|
* for the cpu corresponding to logical cpu 'cpu'. Return true if so,
|
||||||
|
* else false. If 'thread' is non-NULL, the local thread number within the
|
||||||
|
* core is returned in it.
|
||||||
|
*/
|
||||||
|
bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun,
|
||||||
|
int cpu, unsigned int *thread)
|
||||||
|
{
|
||||||
|
/* 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 true;
|
||||||
|
|
||||||
|
if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* of_get_cpu_node - Get device node associated with the given logical CPU
|
* of_get_cpu_node - Get device node associated with the given logical CPU
|
||||||
*
|
*
|
||||||
|
@ -300,24 +325,10 @@ static bool __of_find_n_match_cpu_property(struct device_node *cpun,
|
||||||
*/
|
*/
|
||||||
struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
|
struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
|
||||||
{
|
{
|
||||||
struct device_node *cpun, *cpus;
|
struct device_node *cpun;
|
||||||
|
|
||||||
cpus = of_find_node_by_path("/cpus");
|
for_each_node_by_type(cpun, "cpu") {
|
||||||
if (!cpus)
|
if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread))
|
||||||
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 cpun;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
|
|
||||||
struct device;
|
struct device;
|
||||||
|
struct device_node;
|
||||||
|
|
||||||
struct cpu {
|
struct cpu {
|
||||||
int node_id; /* The node which contains the CPU */
|
int node_id; /* The node which contains the CPU */
|
||||||
|
@ -29,6 +30,8 @@ extern int register_cpu(struct cpu *cpu, int num);
|
||||||
extern struct device *get_cpu_device(unsigned cpu);
|
extern struct device *get_cpu_device(unsigned cpu);
|
||||||
extern bool cpu_is_hotpluggable(unsigned cpu);
|
extern bool cpu_is_hotpluggable(unsigned cpu);
|
||||||
extern bool arch_match_cpu_phys_id(int cpu, u64 phys_id);
|
extern bool arch_match_cpu_phys_id(int cpu, u64 phys_id);
|
||||||
|
extern bool arch_find_n_match_cpu_physical_id(struct device_node *cpun,
|
||||||
|
int cpu, unsigned int *thread);
|
||||||
|
|
||||||
extern int cpu_add_dev_attr(struct device_attribute *attr);
|
extern int cpu_add_dev_attr(struct device_attribute *attr);
|
||||||
extern void cpu_remove_dev_attr(struct device_attribute *attr);
|
extern void cpu_remove_dev_attr(struct device_attribute *attr);
|
||||||
|
|
Loading…
Reference in a new issue