sched/walt: Fix negative count of sched_asym_cpucapacity static key

The current code sets per-cpu variable sd_asym_cpucapacity while
building sched domains even when there are no asymmetric CPUs.
This is done to make sure that EAS remains enabled on a b.L system
after hotplugging out all big/LITTLE CPUs. However it is causing
the below warning during CPU hotplug.

[13988.932604] pc : static_key_slow_dec_cpuslocked+0xe8/0x150
[13988.932608] lr : static_key_slow_dec_cpuslocked+0xe8/0x150
[13988.932610] sp : ffffffc010333c00
[13988.932612] x29: ffffffc010333c00 x28: ffffff8138d88088
[13988.932615] x27: 0000000000000000 x26: 0000000000000081
[13988.932618] x25: ffffff80917efc80 x24: ffffffc010333c60
[13988.932621] x23: ffffffd32bf09c58 x22: 0000000000000000
[13988.932623] x21: 0000000000000000 x20: ffffff80917efc80
[13988.932626] x19: ffffffd32bf0a3e0 x18: ffffff8138039c38
[13988.932628] x17: ffffffd32bf2b000 x16: 0000000000000050
[13988.932631] x15: 0000000000000050 x14: 0000000000040000
[13988.932633] x13: 0000000000000178 x12: 0000000000000001
[13988.932636] x11: 16a9ca5426841300 x10: 16a9ca5426841300
[13988.932639] x9 : 16a9ca5426841300 x8 : 16a9ca5426841300
[13988.932641] x7 : 0000000000000000 x6 : ffffff813f4edadb
[13988.932643] x5 : 0000000000000000 x4 : 0000000000000004
[13988.932646] x3 : ffffffc010333880 x2 : ffffffd32a683a2c
[13988.932648] x1 : ffffffd329355498 x0 : 000000000000001b
[13988.932651] Call trace:
[13988.932656]  static_key_slow_dec_cpuslocked+0xe8/0x150
[13988.932660]  partition_sched_domains_locked+0x1f8/0x80c
[13988.932666]  sched_cpu_deactivate+0x9c/0x13c
[13988.932670]  cpuhp_invoke_callback+0x6ac/0xa8c
[13988.932675]  cpuhp_thread_fun+0x158/0x1ac
[13988.932678]  smpboot_thread_fn+0x244/0x3e4
[13988.932681]  kthread+0x168/0x178
[13988.932685]  ret_from_fork+0x10/0x18

The mismatch between increment/decrement of sched_asym_cpucapacity
static key is resulting in the above warning. It is due to
the fact that the increment happens only when the system really
has asymmetric capacity CPUs. This check is done by going through
each CPU capacity. So when system becomes SMP during hotplug,
the increment never happens. However the decrement of this static
key is done when any of the currently online CPU has per-cpu variable
sd_asym_cpucapacity value as non-NULL. Since we always set this
variable, we run into this issue.

Our goal was to enable EAS on SMP. To achieve that enable EAS and
build perf domains (required for compute energy) irrespective
of per-cpu variable sd_asym_cpucapacity value. In this way we
no longer have to enable sched_asym_cpucapacity feature on SMP
to enable EAS.

Change-Id: Id46f2b80350b742c75195ad6939b814d4695eb07
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
This commit is contained in:
Pavankumar Kondeti
2020-06-13 10:07:02 +05:30
committed by jabashque
parent 1101322b71
commit 50305fb58a

View File

@@ -347,7 +347,14 @@ static bool build_perf_domains(const struct cpumask *cpu_map)
if (!sysctl_sched_energy_aware)
goto free;
/* EAS is enabled for asymmetric CPU capacity topologies. */
/*
* EAS gets disabled when there are no asymmetric capacity
* CPUs in the system. For example, all big CPUs are
* hotplugged out on a b.L system. We want EAS enabled
* all the time to get both power and perf benefits. Apply
* this policy when WALT is enabled.
*/
#ifndef CONFIG_SCHED_WALT
if (!per_cpu(sd_asym_cpucapacity, cpu)) {
if (sched_debug()) {
pr_info("rd %*pbl: CPUs do not have asymmetric capacities\n",
@@ -355,6 +362,7 @@ static bool build_perf_domains(const struct cpumask *cpu_map)
}
goto free;
}
#endif
for_each_cpu(i, cpu_map) {
/* Skip already covered CPUs. */
@@ -639,22 +647,6 @@ static void update_top_cache_domain(int cpu)
rcu_assign_pointer(per_cpu(sd_asym_packing, cpu), sd);
sd = lowest_flag_domain(cpu, SD_ASYM_CPUCAPACITY);
/*
* EAS gets disabled when there are no asymmetric capacity
* CPUs in the system. For example, all big CPUs are
* hotplugged out on a b.L system. We want EAS enabled
* all the time to get both power and perf benefits. So,
* lets assign sd_asym_cpucapacity to the only available
* sched domain. This is also important for a single cluster
* systems which wants to use EAS.
*
* Setting sd_asym_cpucapacity() to a sched domain which
* has all symmetric capacity CPUs is technically incorrect but
* works well for us in getting EAS enabled all the time.
*/
if (!sd)
sd = cpu_rq(cpu)->sd;
rcu_assign_pointer(per_cpu(sd_asym_cpucapacity, cpu), sd);
}