Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp920059pxj; Fri, 4 Jun 2021 01:14:38 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxqdO/ef6+Yxmp/hWcvG10ieBM7lRpS+vfnEDjVBJO5WdjUzu+i7f34KMJ0E0zVljTjE/Z/ X-Received: by 2002:a05:6402:1111:: with SMTP id u17mr3499790edv.87.1622794477960; Fri, 04 Jun 2021 01:14:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1622794477; cv=none; d=google.com; s=arc-20160816; b=S11sLpCeLVsu/Qw2ORqnibuovlNIlbxYpzCqpZapLSgyUHcbttK0yvO1CVxNumOPUe m2fw3S7SzB1IbGdYUkCJY4mmV9wdH2Y66uaBBIWZFOBxfLhCFNHIIOP7vIVG4YExBydL lchteGHUYlSJ6Sfuir1I8Ma0tCzh8ksbsuYeYLUR00L6gaNOHA1Mt+6ptglh9mf8GbNF mgvW9DT6qAi3qSLDYDSVISncs6Y//kzgwSgv4/2IGDgo6wQ35XOYWge4RSAjXYsNbAE0 Lu7ZeP0wyu6rHENp360kjRF8d372w6DIoHYCWAEwshDhj/P+NXVd05N6/PifPXGB0GdW NXWQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from; bh=FtDe4Dmv8sGHUDDmTHWiDWIXcAYfw30/MWZUo/lAKAc=; b=m481XGDgXLcua3fBT/UkInQAXqFI5E3VSD1NZuK8n5WSnUbseMfOD7neU1nLxzGcH4 rVVF0sDzjSesyq00G0NcjhIb7/eFABbumX82Rxkfl0wyM5zHEYEIqMVhOvFMDZ2mrD9H v5ehjBFsvrr5Mx1ma4Knja6Ge05vb46q9yliXXsfJFihmqnU5sSI/02mQzjMfiDWDzK5 9VW6KEzErf0w84c1s7+fleJoyUMrJl7fBr6rQOXUoboSC+HKXUa5vzjdDhQKust4EUk9 t/Chekl+MEWcsh2u51dT/+MdjoG1BdB+7VCEmUOxJVCUd7JeJhX3kJFnim0vbvgjvvFN YZ0w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ka6si4250487ejc.204.2021.06.04.01.14.14; Fri, 04 Jun 2021 01:14:37 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230131AbhFDIMK (ORCPT + 99 others); Fri, 4 Jun 2021 04:12:10 -0400 Received: from foss.arm.com ([217.140.110.172]:60494 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230138AbhFDIMJ (ORCPT ); Fri, 4 Jun 2021 04:12:09 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id ADDC71396; Fri, 4 Jun 2021 01:10:23 -0700 (PDT) Received: from e123648.arm.com (unknown [10.57.3.252]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id DC3CB3F719; Fri, 4 Jun 2021 01:10:18 -0700 (PDT) From: Lukasz Luba To: linux-kernel@vger.kernel.org Cc: linux-pm@vger.kernel.org, peterz@infradead.org, rjw@rjwysocki.net, viresh.kumar@linaro.org, vincent.guittot@linaro.org, qperret@google.com, dietmar.eggemann@arm.com, vincent.donnefort@arm.com, lukasz.luba@arm.com, Beata.Michalska@arm.com, mingo@redhat.com, juri.lelli@redhat.com, rostedt@goodmis.org, segall@google.com, mgorman@suse.de, bristot@redhat.com Subject: [PATCH v2 2/2] sched/cpufreq: Consider reduced CPU capacity in energy calculation Date: Fri, 4 Jun 2021 09:09:54 +0100 Message-Id: <20210604080954.13915-3-lukasz.luba@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210604080954.13915-1-lukasz.luba@arm.com> References: <20210604080954.13915-1-lukasz.luba@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Energy Aware Scheduling (EAS) needs to predict the decisions made by SchedUtil. The map_util_freq() exists to do that. There are corner cases where the max allowed frequency might be reduced (due to thermal). SchedUtil as a CPUFreq governor, is aware of that but EAS is not. This patch aims to address it. SchedUtil stores the maximum allowed frequency in 'sugov_policy::next_freq' field. EAS has to predict that value, which is the real used frequency. That value is made after a call to cpufreq_driver_resolve_freq() which clamps to the CPUFreq policy limits. In the existing code EAS is not able to predict that real frequency. This leads to energy estimation errors. To avoid wrong energy estimation in EAS (due to frequency miss prediction) make sure that the step which calculates Performance Domain frequency, is also aware of the allowed CPU capacity. Furthermore, modify map_util_freq() to not extend the frequency value. Instead, use map_util_perf() to extend the util value in both places: SchedUtil and EAS, but for EAS clamp it to max allowed CPU capacity. In the end, we achieve the same desirable behavior for both subsystems and alignment in regards to the real CPU frequency. Signed-off-by: Lukasz Luba --- include/linux/energy_model.h | 16 +++++++++++++--- include/linux/sched/cpufreq.h | 2 +- kernel/sched/cpufreq_schedutil.c | 1 + kernel/sched/fair.c | 2 +- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/include/linux/energy_model.h b/include/linux/energy_model.h index 757fc60658fa..3f221dbf5f95 100644 --- a/include/linux/energy_model.h +++ b/include/linux/energy_model.h @@ -91,6 +91,8 @@ void em_dev_unregister_perf_domain(struct device *dev); * @pd : performance domain for which energy has to be estimated * @max_util : highest utilization among CPUs of the domain * @sum_util : sum of the utilization of all CPUs in the domain + * @allowed_cpu_cap : maximum allowed CPU capacity for the @pd, which + might reflect reduced frequency (due to thermal) * * This function must be used only for CPU devices. There is no validation, * i.e. if the EM is a CPU type and has cpumask allocated. It is called from @@ -100,7 +102,8 @@ void em_dev_unregister_perf_domain(struct device *dev); * a capacity state satisfying the max utilization of the domain. */ static inline unsigned long em_cpu_energy(struct em_perf_domain *pd, - unsigned long max_util, unsigned long sum_util) + unsigned long max_util, unsigned long sum_util, + unsigned long allowed_cpu_cap) { unsigned long freq, scale_cpu; struct em_perf_state *ps; @@ -112,11 +115,17 @@ static inline unsigned long em_cpu_energy(struct em_perf_domain *pd, /* * In order to predict the performance state, map the utilization of * the most utilized CPU of the performance domain to a requested - * frequency, like schedutil. + * frequency, like schedutil. Take also into account that the real + * frequency might be set lower (due to thermal capping). Thus, clamp + * max utilization to the allowed CPU capacity before calculating + * effective frequency. */ cpu = cpumask_first(to_cpumask(pd->cpus)); scale_cpu = arch_scale_cpu_capacity(cpu); ps = &pd->table[pd->nr_perf_states - 1]; + + max_util = map_util_perf(max_util); + max_util = min(max_util, allowed_cpu_cap); freq = map_util_freq(max_util, ps->frequency, scale_cpu); /* @@ -209,7 +218,8 @@ static inline struct em_perf_domain *em_pd_get(struct device *dev) return NULL; } static inline unsigned long em_cpu_energy(struct em_perf_domain *pd, - unsigned long max_util, unsigned long sum_util) + unsigned long max_util, unsigned long sum_util, + unsigned long allowed_cpu_cap) { return 0; } diff --git a/include/linux/sched/cpufreq.h b/include/linux/sched/cpufreq.h index 6205578ab6ee..bdd31ab93bc5 100644 --- a/include/linux/sched/cpufreq.h +++ b/include/linux/sched/cpufreq.h @@ -26,7 +26,7 @@ bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy); static inline unsigned long map_util_freq(unsigned long util, unsigned long freq, unsigned long cap) { - return (freq + (freq >> 2)) * util / cap; + return freq * util / cap; } static inline unsigned long map_util_perf(unsigned long util) diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index 4f09afd2f321..57124614363d 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -151,6 +151,7 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy, unsigned int freq = arch_scale_freq_invariant() ? policy->cpuinfo.max_freq : policy->cur; + util = map_util_perf(util); freq = map_util_freq(util, freq, max); if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 1aeddecabc20..9a79bbd9425b 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -6590,7 +6590,7 @@ compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd) max_util = max(max_util, min(cpu_util, _cpu_cap)); } - return em_cpu_energy(pd->em_pd, max_util, sum_util); + return em_cpu_energy(pd->em_pd, max_util, sum_util, _cpu_cap); } /* -- 2.17.1