From 73e184bc16c87eebb99c6b62da7e94ccd26af491 Mon Sep 17 00:00:00 2001 From: Dietmar Eggemann Date: Tue, 6 Jun 2017 09:30:23 +0100 Subject: [PATCH] ANDROID: drivers base/arch_topology: enforce SCHED_CAPACITY_SCALE as highest CPU capacity The default CPU capacity is SCHED_CAPACITY_SCALE (1024). On a heterogeneous system (hmp) this value can be smaller for some cpus. The CPU capacity parsing code normalizes the capacity-dmips-mhz properties w.r.t. the highest value found while parsing the DT to SCHED_CAPACITY_SCALE. CPU capacity can also be changed by writing to /sys/devices/system/cpu/cpu*/cpu_capacity. To make sure that a subset of all online cpus still has a CPU capacity value of SCHED_CAPACITY_SCALE enforce in the appropriate sysfs attribute store function cpu_capacity_store(). This will avoid weird setup's like transforming an hmp into an smp system with a CPU capacity < SCHED_CAPACITY_SCALE for all cpus. The current cpu_capacity_store() assumes that all cpus of a cluster have the same CPU capacity value which is true for existing hmp systems (e.g. big.LITTLE). This assumption is also used by this patch. If the new CPU capacity value for a cpu is smaller than SCHED_CAPACITY_SCALE we iterate over the cpus which do not belong to the cpu's cluster and check that there is still a cpu with CPU capacity equal SCHED_CAPACITY_SCALE. The use of &cpu_topology[this_cpu].core_sibling is replaced by topology_core_cpumask(this_cpu). Signed-off-by: Dietmar Eggemann Change-Id: I2a197a012edd9f20b1c794f27567b891c0d2de12 Signed-off-by: Chris Redpath --- drivers/base/arch_topology.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index e6341ac7b394..473f67c40a3c 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -67,6 +67,7 @@ static ssize_t cpu_capacity_store(struct device *dev, int i; unsigned long new_capacity; ssize_t ret; + cpumask_var_t mask; if (!count) return 0; @@ -78,7 +79,35 @@ static ssize_t cpu_capacity_store(struct device *dev, return -EINVAL; mutex_lock(&cpu_scale_mutex); - for_each_cpu(i, &cpu_topology[this_cpu].core_sibling) + + if (new_capacity < SCHED_CAPACITY_SCALE) { + int highest_score_cpu = 0; + + if (!alloc_cpumask_var(&mask, GFP_KERNEL)) { + mutex_unlock(&cpu_scale_mutex); + return -ENOMEM; + } + + cpumask_andnot(mask, cpu_online_mask, + topology_core_cpumask(this_cpu)); + + for_each_cpu(i, mask) { + if (topology_get_cpu_scale(NULL, i) == + SCHED_CAPACITY_SCALE) { + highest_score_cpu = 1; + break; + } + } + + free_cpumask_var(mask); + + if (!highest_score_cpu) { + mutex_unlock(&cpu_scale_mutex); + return -EINVAL; + } + } + + for_each_cpu(i, topology_core_cpumask(this_cpu)) topology_set_cpu_scale(i, new_capacity); mutex_unlock(&cpu_scale_mutex); -- 2.20.1