diff options
author | Juri Lelli <juri.lelli@arm.com> | 2015-01-27 11:24:59 +0000 |
---|---|---|
committer | Robin Randhawa <robin.randhawa@arm.com> | 2015-04-09 12:26:15 +0100 |
commit | 5c4ee2a3d4f44328e35140a5ef82e918d258aca1 (patch) | |
tree | 06dbcc61ab22f0bd97101681d53362a6ddd5cd0e | |
parent | ce35a6abe5dcc43f7d7fdeaa037e6799e445fe6d (diff) |
arm64: Cpu invariant scheduler load-tracking support
Counterpart of the arm bits (slightly different implementation
due to different parsing of the dtb).
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
-rw-r--r-- | arch/arm64/kernel/topology.c | 60 |
1 files changed, 20 insertions, 40 deletions
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 59a48b8b9b44..1bbf17301f10 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -197,9 +197,7 @@ struct cpu_efficiency { * Table of relative efficiency of each processors * The efficiency value must fit in 20bit and the final * cpu_scale value must be in the range - * 0 < cpu_scale < 3*SCHED_CAPACITY_SCALE/2 - * in order to return at most 1 when DIV_ROUND_CLOSEST - * is used to compute the capacity of a CPU. + * 0 < cpu_scale < SCHED_CAPACITY_SCALE. * Processors that are not defined in the table, * use the default SCHED_CAPACITY_SCALE value for cpu_scale. */ @@ -212,15 +210,11 @@ static const struct cpu_efficiency table_efficiency[] = { static unsigned long *__cpu_capacity; #define cpu_capacity(cpu) __cpu_capacity[cpu] -static unsigned long middle_capacity = 1; +static unsigned long max_cpu_perf; /* * Iterate all CPUs' descriptor in DT and compute the efficiency - * (as per table_efficiency). Also calculate a middle efficiency - * as close as possible to (max{eff_i} - min{eff_i}) / 2 - * This is later used to scale the cpu_capacity field such that an - * 'average' CPU is of middle capacity. Also see the comments near - * table_efficiency[] and update_cpu_capacity(). + * (as per table_efficiency). Calculate the max cpu performance too. */ static int __init parse_dt_topology(void) { @@ -269,9 +263,6 @@ static void __init parse_dt_cpu_capacity(void) { const struct cpu_efficiency *cpu_eff; struct device_node *cn; - unsigned long min_capacity = ULONG_MAX; - unsigned long max_capacity = 0; - unsigned long capacity = 0; int cpu; __cpu_capacity = kcalloc(nr_cpu_ids, sizeof(*__cpu_capacity), @@ -280,6 +271,7 @@ static void __init parse_dt_cpu_capacity(void) for_each_possible_cpu(cpu) { const u32 *rate; int len; + unsigned long cpu_perf; /* Too early to use cpu->of_node */ cn = of_get_cpu_node(cpu, NULL); @@ -304,47 +296,35 @@ static void __init parse_dt_cpu_capacity(void) continue; } - capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency; - - /* Save min capacity of the system */ - if (capacity < min_capacity) - min_capacity = capacity; - - /* Save max capacity of the system */ - if (capacity > max_capacity) - max_capacity = capacity; - - cpu_capacity(cpu) = capacity; + cpu_perf = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency; + cpu_capacity(cpu) = cpu_perf; + max_cpu_perf = max(max_cpu_perf, cpu_perf); } - /* If min and max capacities are equal we bypass the update of the - * cpu_scale because all CPUs have the same capacity. Otherwise, we - * compute a middle_capacity factor that will ensure that the capacity - * of an 'average' CPU of the system will be as close as possible to - * SCHED_CAPACITY_SCALE, which is the default value, but with the - * constraint explained near table_efficiency[]. - */ - if (min_capacity == max_capacity) - return; - else if (4 * max_capacity < (3 * (max_capacity + min_capacity))) - middle_capacity = (min_capacity + max_capacity) - >> (SCHED_CAPACITY_SHIFT+1); - else - middle_capacity = ((max_capacity / 3) - >> (SCHED_CAPACITY_SHIFT-1)) + 1; + if (cpu < num_possible_cpus()) + max_cpu_perf = 0; } /* * Look for a customed capacity of a CPU in the cpu_topo_data table during the * boot. The update of all CPUs is in O(n^2) for heteregeneous system but the - * function returns directly for SMP system. + * function returns directly for SMP system or if there is no complete set + * of cpu efficiency, clock frequency data for each cpu. */ static void update_cpu_capacity(unsigned int cpu) { + unsigned long capacity; + if (!cpu_capacity(cpu)) return; - set_capacity_scale(cpu, cpu_capacity(cpu) / middle_capacity); + if (!max_cpu_perf) + cpu_capacity(cpu) = 0; + + capacity = cpu_capacity(cpu); + capacity *= SCHED_CAPACITY_SCALE; + capacity /= max_cpu_perf; + set_capacity_scale(cpu, capacity); pr_info("CPU%d: update cpu_capacity %lu\n", cpu, arch_scale_cpu_capacity(NULL, cpu)); |