2018-12-03 18:29:29 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2016-04-02 07:09:12 +08:00
|
|
|
/*
|
|
|
|
* CPUFreq governor based on scheduler-provided CPU utilization data.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2016, Intel Corporation
|
|
|
|
* Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
|
|
|
*/
|
|
|
|
|
2016-05-18 20:25:28 +08:00
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
|
2016-04-02 07:09:12 +08:00
|
|
|
#include "sched.h"
|
|
|
|
|
sched/cpufreq: Prepare schedutil for Energy Aware Scheduling
Schedutil requests frequency by aggregating utilization signals from
the scheduler (CFS, RT, DL, IRQ) and applying a 25% margin on top of
them. Since Energy Aware Scheduling (EAS) needs to be able to predict
the frequency requests, it needs to forecast the decisions made by the
governor.
In order to prepare the introduction of EAS, introduce
schedutil_freq_util() to centralize the aforementioned signal
aggregation and make it available to both schedutil and EAS. Since
frequency selection and energy estimation still need to deal with RT and
DL signals slightly differently, schedutil_freq_util() is called with a
different 'type' parameter in those two contexts, and returns an
aggregated utilization signal accordingly. While at it, introduce the
map_util_freq() function which is designed to make schedutil's 25%
margin usable easily for both sugov and EAS.
As EAS will be able to predict schedutil's frequency requests more
accurately than any other governor by design, it'd be sensible to make
sure EAS cannot be used without schedutil. This will be done later, once
EAS has actually been introduced.
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Quentin Perret <quentin.perret@arm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: adharmap@codeaurora.org
Cc: chris.redpath@arm.com
Cc: currojerez@riseup.net
Cc: dietmar.eggemann@arm.com
Cc: edubezval@gmail.com
Cc: gregkh@linuxfoundation.org
Cc: javi.merino@kernel.org
Cc: joel@joelfernandes.org
Cc: juri.lelli@redhat.com
Cc: morten.rasmussen@arm.com
Cc: patrick.bellasi@arm.com
Cc: pkondeti@codeaurora.org
Cc: rjw@rjwysocki.net
Cc: skannan@codeaurora.org
Cc: smuckle@google.com
Cc: srinivas.pandruvada@linux.intel.com
Cc: thara.gopinath@linaro.org
Cc: tkjos@google.com
Cc: valentin.schneider@arm.com
Cc: vincent.guittot@linaro.org
Cc: viresh.kumar@linaro.org
Link: https://lkml.kernel.org/r/20181203095628.11858-3-quentin.perret@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-12-03 17:56:15 +08:00
|
|
|
#include <linux/sched/cpufreq.h>
|
2018-03-03 19:20:47 +08:00
|
|
|
#include <trace/events/power.h>
|
|
|
|
|
2019-03-28 18:33:21 +08:00
|
|
|
#define IOWAIT_BOOST_MIN (SCHED_CAPACITY_SCALE / 8)
|
|
|
|
|
2016-04-02 07:09:12 +08:00
|
|
|
struct sugov_tunables {
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
struct gov_attr_set attr_set;
|
|
|
|
unsigned int rate_limit_us;
|
2016-04-02 07:09:12 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct sugov_policy {
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
struct cpufreq_policy *policy;
|
|
|
|
|
|
|
|
struct sugov_tunables *tunables;
|
|
|
|
struct list_head tunables_hook;
|
|
|
|
|
|
|
|
raw_spinlock_t update_lock; /* For shared policies */
|
|
|
|
u64 last_freq_update_time;
|
|
|
|
s64 freq_update_delay_ns;
|
|
|
|
unsigned int next_freq;
|
|
|
|
unsigned int cached_raw_freq;
|
|
|
|
|
|
|
|
/* The next fields are only needed if fast switch cannot be used: */
|
|
|
|
struct irq_work irq_work;
|
|
|
|
struct kthread_work work;
|
|
|
|
struct mutex work_lock;
|
|
|
|
struct kthread_worker worker;
|
|
|
|
struct task_struct *thread;
|
|
|
|
bool work_in_progress;
|
|
|
|
|
2019-08-07 15:06:01 +08:00
|
|
|
bool limits_changed;
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
bool need_freq_update;
|
2016-04-02 07:09:12 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct sugov_cpu {
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
struct update_util_data update_util;
|
|
|
|
struct sugov_policy *sg_policy;
|
|
|
|
unsigned int cpu;
|
2016-04-02 07:09:12 +08:00
|
|
|
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
bool iowait_boost_pending;
|
|
|
|
unsigned int iowait_boost;
|
2018-05-22 19:07:54 +08:00
|
|
|
u64 last_update;
|
2016-07-14 04:25:26 +08:00
|
|
|
|
2018-06-28 23:45:08 +08:00
|
|
|
unsigned long bw_dl;
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
unsigned long max;
|
cpufreq: schedutil: Avoid reducing frequency of busy CPUs prematurely
The way the schedutil governor uses the PELT metric causes it to
underestimate the CPU utilization in some cases.
That can be easily demonstrated by running kernel compilation on
a Sandy Bridge Intel processor, running turbostat in parallel with
it and looking at the values written to the MSR_IA32_PERF_CTL
register. Namely, the expected result would be that when all CPUs
were 100% busy, all of them would be requested to run in the maximum
P-state, but observation shows that this clearly isn't the case.
The CPUs run in the maximum P-state for a while and then are
requested to run slower and go back to the maximum P-state after
a while again. That causes the actual frequency of the processor to
visibly oscillate below the sustainable maximum in a jittery fashion
which clearly is not desirable.
That has been attributed to CPU utilization metric updates on task
migration that cause the total utilization value for the CPU to be
reduced by the utilization of the migrated task. If that happens,
the schedutil governor may see a CPU utilization reduction and will
attempt to reduce the CPU frequency accordingly right away. That
may be premature, though, for example if the system is generally
busy and there are other runnable tasks waiting to be run on that
CPU already.
This is unlikely to be an issue on systems where cpufreq policies are
shared between multiple CPUs, because in those cases the policy
utilization is computed as the maximum of the CPU utilization values
over the whole policy and if that turns out to be low, reducing the
frequency for the policy most likely is a good idea anyway. On
systems with one CPU per policy, however, it may affect performance
adversely and even lead to increased energy consumption in some cases.
On those systems it may be addressed by taking another utilization
metric into consideration, like whether or not the CPU whose
frequency is about to be reduced has been idle recently, because if
that's not the case, the CPU is likely to be busy in the near future
and its frequency should not be reduced.
To that end, use the counter of idle calls in the timekeeping code.
Namely, make the schedutil governor look at that counter for the
current CPU every time before its frequency is about to be reduced.
If the counter has not changed since the previous iteration of the
governor computations for that CPU, the CPU has been busy for all
that time and its frequency should not be decreased, so if the new
frequency would be lower than the one set previously, the governor
will skip the frequency update.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Joel Fernandes <joelaf@google.com>
2017-03-22 07:08:50 +08:00
|
|
|
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
/* The field below is for single-CPU policies only: */
|
cpufreq: schedutil: Avoid reducing frequency of busy CPUs prematurely
The way the schedutil governor uses the PELT metric causes it to
underestimate the CPU utilization in some cases.
That can be easily demonstrated by running kernel compilation on
a Sandy Bridge Intel processor, running turbostat in parallel with
it and looking at the values written to the MSR_IA32_PERF_CTL
register. Namely, the expected result would be that when all CPUs
were 100% busy, all of them would be requested to run in the maximum
P-state, but observation shows that this clearly isn't the case.
The CPUs run in the maximum P-state for a while and then are
requested to run slower and go back to the maximum P-state after
a while again. That causes the actual frequency of the processor to
visibly oscillate below the sustainable maximum in a jittery fashion
which clearly is not desirable.
That has been attributed to CPU utilization metric updates on task
migration that cause the total utilization value for the CPU to be
reduced by the utilization of the migrated task. If that happens,
the schedutil governor may see a CPU utilization reduction and will
attempt to reduce the CPU frequency accordingly right away. That
may be premature, though, for example if the system is generally
busy and there are other runnable tasks waiting to be run on that
CPU already.
This is unlikely to be an issue on systems where cpufreq policies are
shared between multiple CPUs, because in those cases the policy
utilization is computed as the maximum of the CPU utilization values
over the whole policy and if that turns out to be low, reducing the
frequency for the policy most likely is a good idea anyway. On
systems with one CPU per policy, however, it may affect performance
adversely and even lead to increased energy consumption in some cases.
On those systems it may be addressed by taking another utilization
metric into consideration, like whether or not the CPU whose
frequency is about to be reduced has been idle recently, because if
that's not the case, the CPU is likely to be busy in the near future
and its frequency should not be reduced.
To that end, use the counter of idle calls in the timekeeping code.
Namely, make the schedutil governor look at that counter for the
current CPU every time before its frequency is about to be reduced.
If the counter has not changed since the previous iteration of the
governor computations for that CPU, the CPU has been busy for all
that time and its frequency should not be decreased, so if the new
frequency would be lower than the one set previously, the governor
will skip the frequency update.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Joel Fernandes <joelaf@google.com>
2017-03-22 07:08:50 +08:00
|
|
|
#ifdef CONFIG_NO_HZ_COMMON
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
unsigned long saved_idle_calls;
|
cpufreq: schedutil: Avoid reducing frequency of busy CPUs prematurely
The way the schedutil governor uses the PELT metric causes it to
underestimate the CPU utilization in some cases.
That can be easily demonstrated by running kernel compilation on
a Sandy Bridge Intel processor, running turbostat in parallel with
it and looking at the values written to the MSR_IA32_PERF_CTL
register. Namely, the expected result would be that when all CPUs
were 100% busy, all of them would be requested to run in the maximum
P-state, but observation shows that this clearly isn't the case.
The CPUs run in the maximum P-state for a while and then are
requested to run slower and go back to the maximum P-state after
a while again. That causes the actual frequency of the processor to
visibly oscillate below the sustainable maximum in a jittery fashion
which clearly is not desirable.
That has been attributed to CPU utilization metric updates on task
migration that cause the total utilization value for the CPU to be
reduced by the utilization of the migrated task. If that happens,
the schedutil governor may see a CPU utilization reduction and will
attempt to reduce the CPU frequency accordingly right away. That
may be premature, though, for example if the system is generally
busy and there are other runnable tasks waiting to be run on that
CPU already.
This is unlikely to be an issue on systems where cpufreq policies are
shared between multiple CPUs, because in those cases the policy
utilization is computed as the maximum of the CPU utilization values
over the whole policy and if that turns out to be low, reducing the
frequency for the policy most likely is a good idea anyway. On
systems with one CPU per policy, however, it may affect performance
adversely and even lead to increased energy consumption in some cases.
On those systems it may be addressed by taking another utilization
metric into consideration, like whether or not the CPU whose
frequency is about to be reduced has been idle recently, because if
that's not the case, the CPU is likely to be busy in the near future
and its frequency should not be reduced.
To that end, use the counter of idle calls in the timekeeping code.
Namely, make the schedutil governor look at that counter for the
current CPU every time before its frequency is about to be reduced.
If the counter has not changed since the previous iteration of the
governor computations for that CPU, the CPU has been busy for all
that time and its frequency should not be decreased, so if the new
frequency would be lower than the one set previously, the governor
will skip the frequency update.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Joel Fernandes <joelaf@google.com>
2017-03-22 07:08:50 +08:00
|
|
|
#endif
|
2016-04-02 07:09:12 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static DEFINE_PER_CPU(struct sugov_cpu, sugov_cpu);
|
|
|
|
|
|
|
|
/************************ Governor internals ***********************/
|
|
|
|
|
|
|
|
static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
|
|
|
|
{
|
|
|
|
s64 delta_ns;
|
|
|
|
|
sched: cpufreq: Allow remote cpufreq callbacks
With Android UI and benchmarks the latency of cpufreq response to
certain scheduling events can become very critical. Currently, callbacks
into cpufreq governors are only made from the scheduler if the target
CPU of the event is the same as the current CPU. This means there are
certain situations where a target CPU may not run the cpufreq governor
for some time.
One testcase to show this behavior is where a task starts running on
CPU0, then a new task is also spawned on CPU0 by a task on CPU1. If the
system is configured such that the new tasks should receive maximum
demand initially, this should result in CPU0 increasing frequency
immediately. But because of the above mentioned limitation though, this
does not occur.
This patch updates the scheduler core to call the cpufreq callbacks for
remote CPUs as well.
The schedutil, ondemand and conservative governors are updated to
process cpufreq utilization update hooks called for remote CPUs where
the remote CPU is managed by the cpufreq policy of the local CPU.
The intel_pstate driver is updated to always reject remote callbacks.
This is tested with couple of usecases (Android: hackbench, recentfling,
galleryfling, vellamo, Ubuntu: hackbench) on ARM hikey board (64 bit
octa-core, single policy). Only galleryfling showed minor improvements,
while others didn't had much deviation.
The reason being that this patch only targets a corner case, where
following are required to be true to improve performance and that
doesn't happen too often with these tests:
- Task is migrated to another CPU.
- The task has high demand, and should take the target CPU to higher
OPPs.
- And the target CPU doesn't call into the cpufreq governor until the
next tick.
Based on initial work from Steve Muckle.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Saravana Kannan <skannan@codeaurora.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-07-28 14:46:38 +08:00
|
|
|
/*
|
|
|
|
* Since cpufreq_update_util() is called with rq->lock held for
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
* the @target_cpu, our per-CPU data is fully serialized.
|
sched: cpufreq: Allow remote cpufreq callbacks
With Android UI and benchmarks the latency of cpufreq response to
certain scheduling events can become very critical. Currently, callbacks
into cpufreq governors are only made from the scheduler if the target
CPU of the event is the same as the current CPU. This means there are
certain situations where a target CPU may not run the cpufreq governor
for some time.
One testcase to show this behavior is where a task starts running on
CPU0, then a new task is also spawned on CPU0 by a task on CPU1. If the
system is configured such that the new tasks should receive maximum
demand initially, this should result in CPU0 increasing frequency
immediately. But because of the above mentioned limitation though, this
does not occur.
This patch updates the scheduler core to call the cpufreq callbacks for
remote CPUs as well.
The schedutil, ondemand and conservative governors are updated to
process cpufreq utilization update hooks called for remote CPUs where
the remote CPU is managed by the cpufreq policy of the local CPU.
The intel_pstate driver is updated to always reject remote callbacks.
This is tested with couple of usecases (Android: hackbench, recentfling,
galleryfling, vellamo, Ubuntu: hackbench) on ARM hikey board (64 bit
octa-core, single policy). Only galleryfling showed minor improvements,
while others didn't had much deviation.
The reason being that this patch only targets a corner case, where
following are required to be true to improve performance and that
doesn't happen too often with these tests:
- Task is migrated to another CPU.
- The task has high demand, and should take the target CPU to higher
OPPs.
- And the target CPU doesn't call into the cpufreq governor until the
next tick.
Based on initial work from Steve Muckle.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Saravana Kannan <skannan@codeaurora.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-07-28 14:46:38 +08:00
|
|
|
*
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
* However, drivers cannot in general deal with cross-CPU
|
sched: cpufreq: Allow remote cpufreq callbacks
With Android UI and benchmarks the latency of cpufreq response to
certain scheduling events can become very critical. Currently, callbacks
into cpufreq governors are only made from the scheduler if the target
CPU of the event is the same as the current CPU. This means there are
certain situations where a target CPU may not run the cpufreq governor
for some time.
One testcase to show this behavior is where a task starts running on
CPU0, then a new task is also spawned on CPU0 by a task on CPU1. If the
system is configured such that the new tasks should receive maximum
demand initially, this should result in CPU0 increasing frequency
immediately. But because of the above mentioned limitation though, this
does not occur.
This patch updates the scheduler core to call the cpufreq callbacks for
remote CPUs as well.
The schedutil, ondemand and conservative governors are updated to
process cpufreq utilization update hooks called for remote CPUs where
the remote CPU is managed by the cpufreq policy of the local CPU.
The intel_pstate driver is updated to always reject remote callbacks.
This is tested with couple of usecases (Android: hackbench, recentfling,
galleryfling, vellamo, Ubuntu: hackbench) on ARM hikey board (64 bit
octa-core, single policy). Only galleryfling showed minor improvements,
while others didn't had much deviation.
The reason being that this patch only targets a corner case, where
following are required to be true to improve performance and that
doesn't happen too often with these tests:
- Task is migrated to another CPU.
- The task has high demand, and should take the target CPU to higher
OPPs.
- And the target CPU doesn't call into the cpufreq governor until the
next tick.
Based on initial work from Steve Muckle.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Saravana Kannan <skannan@codeaurora.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-07-28 14:46:38 +08:00
|
|
|
* requests, so while get_next_freq() will work, our
|
2017-08-14 17:20:16 +08:00
|
|
|
* sugov_update_commit() call may not for the fast switching platforms.
|
sched: cpufreq: Allow remote cpufreq callbacks
With Android UI and benchmarks the latency of cpufreq response to
certain scheduling events can become very critical. Currently, callbacks
into cpufreq governors are only made from the scheduler if the target
CPU of the event is the same as the current CPU. This means there are
certain situations where a target CPU may not run the cpufreq governor
for some time.
One testcase to show this behavior is where a task starts running on
CPU0, then a new task is also spawned on CPU0 by a task on CPU1. If the
system is configured such that the new tasks should receive maximum
demand initially, this should result in CPU0 increasing frequency
immediately. But because of the above mentioned limitation though, this
does not occur.
This patch updates the scheduler core to call the cpufreq callbacks for
remote CPUs as well.
The schedutil, ondemand and conservative governors are updated to
process cpufreq utilization update hooks called for remote CPUs where
the remote CPU is managed by the cpufreq policy of the local CPU.
The intel_pstate driver is updated to always reject remote callbacks.
This is tested with couple of usecases (Android: hackbench, recentfling,
galleryfling, vellamo, Ubuntu: hackbench) on ARM hikey board (64 bit
octa-core, single policy). Only galleryfling showed minor improvements,
while others didn't had much deviation.
The reason being that this patch only targets a corner case, where
following are required to be true to improve performance and that
doesn't happen too often with these tests:
- Task is migrated to another CPU.
- The task has high demand, and should take the target CPU to higher
OPPs.
- And the target CPU doesn't call into the cpufreq governor until the
next tick.
Based on initial work from Steve Muckle.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Saravana Kannan <skannan@codeaurora.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-07-28 14:46:38 +08:00
|
|
|
*
|
|
|
|
* Hence stop here for remote requests if they aren't supported
|
|
|
|
* by the hardware, as calculating the frequency is pointless if
|
|
|
|
* we cannot in fact act on it.
|
2017-08-14 17:20:16 +08:00
|
|
|
*
|
cpufreq: Avoid leaving stale IRQ work items during CPU offline
The scheduler code calling cpufreq_update_util() may run during CPU
offline on the target CPU after the IRQ work lists have been flushed
for it, so the target CPU should be prevented from running code that
may queue up an IRQ work item on it at that point.
Unfortunately, that may not be the case if dvfs_possible_from_any_cpu
is set for at least one cpufreq policy in the system, because that
allows the CPU going offline to run the utilization update callback
of the cpufreq governor on behalf of another (online) CPU in some
cases.
If that happens, the cpufreq governor callback may queue up an IRQ
work on the CPU running it, which is going offline, and the IRQ work
may not be flushed after that point. Moreover, that IRQ work cannot
be flushed until the "offlining" CPU goes back online, so if any
other CPU calls irq_work_sync() to wait for the completion of that
IRQ work, it will have to wait until the "offlining" CPU is back
online and that may not happen forever. In particular, a system-wide
deadlock may occur during CPU online as a result of that.
The failing scenario is as follows. CPU0 is the boot CPU, so it
creates a cpufreq policy and becomes the "leader" of it
(policy->cpu). It cannot go offline, because it is the boot CPU.
Next, other CPUs join the cpufreq policy as they go online and they
leave it when they go offline. The last CPU to go offline, say CPU3,
may queue up an IRQ work while running the governor callback on
behalf of CPU0 after leaving the cpufreq policy because of the
dvfs_possible_from_any_cpu effect described above. Then, CPU0 is
the only online CPU in the system and the stale IRQ work is still
queued on CPU3. When, say, CPU1 goes back online, it will run
irq_work_sync() to wait for that IRQ work to complete and so it
will wait for CPU3 to go back online (which may never happen even
in principle), but (worse yet) CPU0 is waiting for CPU1 at that
point too and a system-wide deadlock occurs.
To address this problem notice that CPUs which cannot run cpufreq
utilization update code for themselves (for example, because they
have left the cpufreq policies that they belonged to), should also
be prevented from running that code on behalf of the other CPUs that
belong to a cpufreq policy with dvfs_possible_from_any_cpu set and so
in that case the cpufreq_update_util_data pointer of the CPU running
the code must not be NULL as well as for the CPU which is the target
of the cpufreq utilization update in progress.
Accordingly, change cpufreq_this_cpu_can_update() into a regular
function in kernel/sched/cpufreq.c (instead of a static inline in a
header file) and make it check the cpufreq_update_util_data pointer
of the local CPU if dvfs_possible_from_any_cpu is set for the target
cpufreq policy.
Also update the schedutil governor to do the
cpufreq_this_cpu_can_update() check in the non-fast-switch
case too to avoid the stale IRQ work issues.
Fixes: 99d14d0e16fa ("cpufreq: Process remote callbacks from any CPU if the platform permits")
Link: https://lore.kernel.org/linux-pm/20191121093557.bycvdo4xyinbc5cb@vireshk-i7/
Reported-by: Anson Huang <anson.huang@nxp.com>
Tested-by: Anson Huang <anson.huang@nxp.com>
Cc: 4.14+ <stable@vger.kernel.org> # 4.14+
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Tested-by: Peng Fan <peng.fan@nxp.com> (i.MX8QXP-MEK)
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-12-11 18:28:41 +08:00
|
|
|
* This is needed on the slow switching platforms too to prevent CPUs
|
|
|
|
* going offline from leaving stale IRQ work items behind.
|
sched: cpufreq: Allow remote cpufreq callbacks
With Android UI and benchmarks the latency of cpufreq response to
certain scheduling events can become very critical. Currently, callbacks
into cpufreq governors are only made from the scheduler if the target
CPU of the event is the same as the current CPU. This means there are
certain situations where a target CPU may not run the cpufreq governor
for some time.
One testcase to show this behavior is where a task starts running on
CPU0, then a new task is also spawned on CPU0 by a task on CPU1. If the
system is configured such that the new tasks should receive maximum
demand initially, this should result in CPU0 increasing frequency
immediately. But because of the above mentioned limitation though, this
does not occur.
This patch updates the scheduler core to call the cpufreq callbacks for
remote CPUs as well.
The schedutil, ondemand and conservative governors are updated to
process cpufreq utilization update hooks called for remote CPUs where
the remote CPU is managed by the cpufreq policy of the local CPU.
The intel_pstate driver is updated to always reject remote callbacks.
This is tested with couple of usecases (Android: hackbench, recentfling,
galleryfling, vellamo, Ubuntu: hackbench) on ARM hikey board (64 bit
octa-core, single policy). Only galleryfling showed minor improvements,
while others didn't had much deviation.
The reason being that this patch only targets a corner case, where
following are required to be true to improve performance and that
doesn't happen too often with these tests:
- Task is migrated to another CPU.
- The task has high demand, and should take the target CPU to higher
OPPs.
- And the target CPU doesn't call into the cpufreq governor until the
next tick.
Based on initial work from Steve Muckle.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Saravana Kannan <skannan@codeaurora.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-07-28 14:46:38 +08:00
|
|
|
*/
|
cpufreq: Avoid leaving stale IRQ work items during CPU offline
The scheduler code calling cpufreq_update_util() may run during CPU
offline on the target CPU after the IRQ work lists have been flushed
for it, so the target CPU should be prevented from running code that
may queue up an IRQ work item on it at that point.
Unfortunately, that may not be the case if dvfs_possible_from_any_cpu
is set for at least one cpufreq policy in the system, because that
allows the CPU going offline to run the utilization update callback
of the cpufreq governor on behalf of another (online) CPU in some
cases.
If that happens, the cpufreq governor callback may queue up an IRQ
work on the CPU running it, which is going offline, and the IRQ work
may not be flushed after that point. Moreover, that IRQ work cannot
be flushed until the "offlining" CPU goes back online, so if any
other CPU calls irq_work_sync() to wait for the completion of that
IRQ work, it will have to wait until the "offlining" CPU is back
online and that may not happen forever. In particular, a system-wide
deadlock may occur during CPU online as a result of that.
The failing scenario is as follows. CPU0 is the boot CPU, so it
creates a cpufreq policy and becomes the "leader" of it
(policy->cpu). It cannot go offline, because it is the boot CPU.
Next, other CPUs join the cpufreq policy as they go online and they
leave it when they go offline. The last CPU to go offline, say CPU3,
may queue up an IRQ work while running the governor callback on
behalf of CPU0 after leaving the cpufreq policy because of the
dvfs_possible_from_any_cpu effect described above. Then, CPU0 is
the only online CPU in the system and the stale IRQ work is still
queued on CPU3. When, say, CPU1 goes back online, it will run
irq_work_sync() to wait for that IRQ work to complete and so it
will wait for CPU3 to go back online (which may never happen even
in principle), but (worse yet) CPU0 is waiting for CPU1 at that
point too and a system-wide deadlock occurs.
To address this problem notice that CPUs which cannot run cpufreq
utilization update code for themselves (for example, because they
have left the cpufreq policies that they belonged to), should also
be prevented from running that code on behalf of the other CPUs that
belong to a cpufreq policy with dvfs_possible_from_any_cpu set and so
in that case the cpufreq_update_util_data pointer of the CPU running
the code must not be NULL as well as for the CPU which is the target
of the cpufreq utilization update in progress.
Accordingly, change cpufreq_this_cpu_can_update() into a regular
function in kernel/sched/cpufreq.c (instead of a static inline in a
header file) and make it check the cpufreq_update_util_data pointer
of the local CPU if dvfs_possible_from_any_cpu is set for the target
cpufreq policy.
Also update the schedutil governor to do the
cpufreq_this_cpu_can_update() check in the non-fast-switch
case too to avoid the stale IRQ work issues.
Fixes: 99d14d0e16fa ("cpufreq: Process remote callbacks from any CPU if the platform permits")
Link: https://lore.kernel.org/linux-pm/20191121093557.bycvdo4xyinbc5cb@vireshk-i7/
Reported-by: Anson Huang <anson.huang@nxp.com>
Tested-by: Anson Huang <anson.huang@nxp.com>
Cc: 4.14+ <stable@vger.kernel.org> # 4.14+
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Tested-by: Peng Fan <peng.fan@nxp.com> (i.MX8QXP-MEK)
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-12-11 18:28:41 +08:00
|
|
|
if (!cpufreq_this_cpu_can_update(sg_policy->policy))
|
sched: cpufreq: Allow remote cpufreq callbacks
With Android UI and benchmarks the latency of cpufreq response to
certain scheduling events can become very critical. Currently, callbacks
into cpufreq governors are only made from the scheduler if the target
CPU of the event is the same as the current CPU. This means there are
certain situations where a target CPU may not run the cpufreq governor
for some time.
One testcase to show this behavior is where a task starts running on
CPU0, then a new task is also spawned on CPU0 by a task on CPU1. If the
system is configured such that the new tasks should receive maximum
demand initially, this should result in CPU0 increasing frequency
immediately. But because of the above mentioned limitation though, this
does not occur.
This patch updates the scheduler core to call the cpufreq callbacks for
remote CPUs as well.
The schedutil, ondemand and conservative governors are updated to
process cpufreq utilization update hooks called for remote CPUs where
the remote CPU is managed by the cpufreq policy of the local CPU.
The intel_pstate driver is updated to always reject remote callbacks.
This is tested with couple of usecases (Android: hackbench, recentfling,
galleryfling, vellamo, Ubuntu: hackbench) on ARM hikey board (64 bit
octa-core, single policy). Only galleryfling showed minor improvements,
while others didn't had much deviation.
The reason being that this patch only targets a corner case, where
following are required to be true to improve performance and that
doesn't happen too often with these tests:
- Task is migrated to another CPU.
- The task has high demand, and should take the target CPU to higher
OPPs.
- And the target CPU doesn't call into the cpufreq governor until the
next tick.
Based on initial work from Steve Muckle.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Saravana Kannan <skannan@codeaurora.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-07-28 14:46:38 +08:00
|
|
|
return false;
|
|
|
|
|
2019-08-07 15:06:01 +08:00
|
|
|
if (unlikely(sg_policy->limits_changed)) {
|
|
|
|
sg_policy->limits_changed = false;
|
|
|
|
sg_policy->need_freq_update = true;
|
2016-04-02 07:09:12 +08:00
|
|
|
return true;
|
2019-08-07 15:06:01 +08:00
|
|
|
}
|
2016-04-02 07:09:12 +08:00
|
|
|
|
|
|
|
delta_ns = time - sg_policy->last_freq_update_time;
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
|
2016-04-02 07:09:12 +08:00
|
|
|
return delta_ns >= sg_policy->freq_update_delay_ns;
|
|
|
|
}
|
|
|
|
|
2018-05-23 17:47:45 +08:00
|
|
|
static bool sugov_update_next_freq(struct sugov_policy *sg_policy, u64 time,
|
|
|
|
unsigned int next_freq)
|
2016-04-02 07:09:12 +08:00
|
|
|
{
|
cpufreq: schedutil: Don't skip freq update if need_freq_update is set
The cpufreq policy's frequency limits (min/max) can get changed at any
point of time, while schedutil is trying to update the next frequency.
Though the schedutil governor has necessary locking and support in place
to make sure we don't miss any of those updates, there is a corner case
where the governor will find that the CPU is already running at the
desired frequency and so may skip an update.
For example, consider that the CPU can run at 1 GHz, 1.2 GHz and 1.4 GHz
and is running at 1 GHz currently. Schedutil tries to update the
frequency to 1.2 GHz, during this time the policy limits get changed as
policy->min = 1.4 GHz. As schedutil (and cpufreq core) does clamp the
frequency at various instances, we will eventually set the frequency to
1.4 GHz, while we will save 1.2 GHz in sg_policy->next_freq.
Now lets say the policy limits get changed back at this time with
policy->min as 1 GHz. The next time schedutil is invoked by the
scheduler, we will reevaluate the next frequency (because
need_freq_update will get set due to limits change event) and lets say
we want to set the frequency to 1.2 GHz again. At this point
sugov_update_next_freq() will find the next_freq == current_freq and
will abort the update, while the CPU actually runs at 1.4 GHz.
Until now need_freq_update was used as a flag to indicate that the
policy's frequency limits have changed, and that we should consider the
new limits while reevaluating the next frequency.
This patch fixes the above mentioned issue by extending the purpose of
the need_freq_update flag. If this flag is set now, the schedutil
governor will not try to abort a frequency change even if next_freq ==
current_freq.
As similar behavior is required in the case of
CPUFREQ_NEED_UPDATE_LIMITS flag as well, need_freq_update will never be
set to false if that flag is set for the driver.
We also don't need to consider the need_freq_update flag in
sugov_update_single() anymore to handle the special case of busy CPU, as
we won't abort a frequency update anymore.
Reported-by: zhuguangqing <zhuguangqing@xiaomi.com>
Suggested-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
[ rjw: Rearrange code to avoid a branch ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2020-10-30 15:21:08 +08:00
|
|
|
if (!sg_policy->need_freq_update) {
|
|
|
|
if (sg_policy->next_freq == next_freq)
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS);
|
|
|
|
}
|
2017-03-23 01:32:47 +08:00
|
|
|
|
|
|
|
sg_policy->next_freq = next_freq;
|
2016-04-02 07:09:12 +08:00
|
|
|
sg_policy->last_freq_update_time = time;
|
|
|
|
|
2018-05-23 17:47:45 +08:00
|
|
|
return true;
|
|
|
|
}
|
2016-04-02 07:09:12 +08:00
|
|
|
|
2018-05-23 17:47:45 +08:00
|
|
|
static void sugov_fast_switch(struct sugov_policy *sg_policy, u64 time,
|
|
|
|
unsigned int next_freq)
|
|
|
|
{
|
2020-10-06 20:01:31 +08:00
|
|
|
if (sugov_update_next_freq(sg_policy, time, next_freq))
|
|
|
|
cpufreq_driver_fast_switch(sg_policy->policy, next_freq);
|
2018-05-23 17:47:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void sugov_deferred_update(struct sugov_policy *sg_policy, u64 time,
|
|
|
|
unsigned int next_freq)
|
|
|
|
{
|
|
|
|
if (!sugov_update_next_freq(sg_policy, time, next_freq))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!sg_policy->work_in_progress) {
|
2016-04-02 07:09:12 +08:00
|
|
|
sg_policy->work_in_progress = true;
|
|
|
|
irq_work_queue(&sg_policy->irq_work);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get_next_freq - Compute a new frequency for a given cpufreq policy.
|
2017-03-02 16:33:21 +08:00
|
|
|
* @sg_policy: schedutil policy object to compute the new frequency for.
|
2016-04-02 07:09:12 +08:00
|
|
|
* @util: Current CPU utilization.
|
|
|
|
* @max: CPU capacity.
|
|
|
|
*
|
|
|
|
* If the utilization is frequency-invariant, choose the new frequency to be
|
|
|
|
* proportional to it, that is
|
|
|
|
*
|
|
|
|
* next_freq = C * max_freq * util / max
|
|
|
|
*
|
|
|
|
* Otherwise, approximate the would-be frequency-invariant utilization by
|
|
|
|
* util_raw * (curr_freq / max_freq) which leads to
|
|
|
|
*
|
|
|
|
* next_freq = C * curr_freq * util_raw / max
|
|
|
|
*
|
|
|
|
* Take C = 1.25 for the frequency tipping point at (util / max) = 0.8.
|
2016-07-14 04:25:26 +08:00
|
|
|
*
|
|
|
|
* The lowest driver-supported frequency which is equal or greater than the raw
|
|
|
|
* next_freq (as calculated above) is returned, subject to policy min/max and
|
|
|
|
* cpufreq driver limitations.
|
2016-04-02 07:09:12 +08:00
|
|
|
*/
|
2017-03-02 16:33:21 +08:00
|
|
|
static unsigned int get_next_freq(struct sugov_policy *sg_policy,
|
|
|
|
unsigned long util, unsigned long max)
|
2016-04-02 07:09:12 +08:00
|
|
|
{
|
2016-07-14 04:25:26 +08:00
|
|
|
struct cpufreq_policy *policy = sg_policy->policy;
|
2016-04-02 07:09:12 +08:00
|
|
|
unsigned int freq = arch_scale_freq_invariant() ?
|
|
|
|
policy->cpuinfo.max_freq : policy->cur;
|
|
|
|
|
sched/cpufreq: Prepare schedutil for Energy Aware Scheduling
Schedutil requests frequency by aggregating utilization signals from
the scheduler (CFS, RT, DL, IRQ) and applying a 25% margin on top of
them. Since Energy Aware Scheduling (EAS) needs to be able to predict
the frequency requests, it needs to forecast the decisions made by the
governor.
In order to prepare the introduction of EAS, introduce
schedutil_freq_util() to centralize the aforementioned signal
aggregation and make it available to both schedutil and EAS. Since
frequency selection and energy estimation still need to deal with RT and
DL signals slightly differently, schedutil_freq_util() is called with a
different 'type' parameter in those two contexts, and returns an
aggregated utilization signal accordingly. While at it, introduce the
map_util_freq() function which is designed to make schedutil's 25%
margin usable easily for both sugov and EAS.
As EAS will be able to predict schedutil's frequency requests more
accurately than any other governor by design, it'd be sensible to make
sure EAS cannot be used without schedutil. This will be done later, once
EAS has actually been introduced.
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Quentin Perret <quentin.perret@arm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: adharmap@codeaurora.org
Cc: chris.redpath@arm.com
Cc: currojerez@riseup.net
Cc: dietmar.eggemann@arm.com
Cc: edubezval@gmail.com
Cc: gregkh@linuxfoundation.org
Cc: javi.merino@kernel.org
Cc: joel@joelfernandes.org
Cc: juri.lelli@redhat.com
Cc: morten.rasmussen@arm.com
Cc: patrick.bellasi@arm.com
Cc: pkondeti@codeaurora.org
Cc: rjw@rjwysocki.net
Cc: skannan@codeaurora.org
Cc: smuckle@google.com
Cc: srinivas.pandruvada@linux.intel.com
Cc: thara.gopinath@linaro.org
Cc: tkjos@google.com
Cc: valentin.schneider@arm.com
Cc: vincent.guittot@linaro.org
Cc: viresh.kumar@linaro.org
Link: https://lkml.kernel.org/r/20181203095628.11858-3-quentin.perret@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-12-03 17:56:15 +08:00
|
|
|
freq = map_util_freq(util, freq, max);
|
2016-07-14 04:25:26 +08:00
|
|
|
|
cpufreq: schedutil: Don't skip freq update if need_freq_update is set
The cpufreq policy's frequency limits (min/max) can get changed at any
point of time, while schedutil is trying to update the next frequency.
Though the schedutil governor has necessary locking and support in place
to make sure we don't miss any of those updates, there is a corner case
where the governor will find that the CPU is already running at the
desired frequency and so may skip an update.
For example, consider that the CPU can run at 1 GHz, 1.2 GHz and 1.4 GHz
and is running at 1 GHz currently. Schedutil tries to update the
frequency to 1.2 GHz, during this time the policy limits get changed as
policy->min = 1.4 GHz. As schedutil (and cpufreq core) does clamp the
frequency at various instances, we will eventually set the frequency to
1.4 GHz, while we will save 1.2 GHz in sg_policy->next_freq.
Now lets say the policy limits get changed back at this time with
policy->min as 1 GHz. The next time schedutil is invoked by the
scheduler, we will reevaluate the next frequency (because
need_freq_update will get set due to limits change event) and lets say
we want to set the frequency to 1.2 GHz again. At this point
sugov_update_next_freq() will find the next_freq == current_freq and
will abort the update, while the CPU actually runs at 1.4 GHz.
Until now need_freq_update was used as a flag to indicate that the
policy's frequency limits have changed, and that we should consider the
new limits while reevaluating the next frequency.
This patch fixes the above mentioned issue by extending the purpose of
the need_freq_update flag. If this flag is set now, the schedutil
governor will not try to abort a frequency change even if next_freq ==
current_freq.
As similar behavior is required in the case of
CPUFREQ_NEED_UPDATE_LIMITS flag as well, need_freq_update will never be
set to false if that flag is set for the driver.
We also don't need to consider the need_freq_update flag in
sugov_update_single() anymore to handle the special case of busy CPU, as
we won't abort a frequency update anymore.
Reported-by: zhuguangqing <zhuguangqing@xiaomi.com>
Suggested-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
[ rjw: Rearrange code to avoid a branch ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2020-10-30 15:21:08 +08:00
|
|
|
if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update)
|
2016-07-14 04:25:26 +08:00
|
|
|
return sg_policy->next_freq;
|
2018-05-09 18:35:24 +08:00
|
|
|
|
2017-03-02 16:33:20 +08:00
|
|
|
sg_policy->cached_raw_freq = freq;
|
2016-07-14 04:25:26 +08:00
|
|
|
return cpufreq_driver_resolve_freq(policy, freq);
|
2016-04-02 07:09:12 +08:00
|
|
|
}
|
|
|
|
|
2018-07-05 20:36:17 +08:00
|
|
|
/*
|
|
|
|
* This function computes an effective utilization for the given CPU, to be
|
|
|
|
* used for frequency selection given the linear relation: f = u * f_max.
|
|
|
|
*
|
|
|
|
* The scheduler tracks the following metrics:
|
|
|
|
*
|
|
|
|
* cpu_util_{cfs,rt,dl,irq}()
|
|
|
|
* cpu_bw_dl()
|
|
|
|
*
|
|
|
|
* Where the cfs,rt and dl util numbers are tracked with the same metric and
|
|
|
|
* synchronized windows and are thus directly comparable.
|
|
|
|
*
|
|
|
|
* The cfs,rt,dl utilization are the running times measured with rq->clock_task
|
|
|
|
* which excludes things like IRQ and steal-time. These latter are then accrued
|
|
|
|
* in the irq utilization.
|
|
|
|
*
|
|
|
|
* The DL bandwidth number otoh is not a measured metric but a value computed
|
|
|
|
* based on the task model parameters and gives the minimal utilization
|
|
|
|
* required to meet deadlines.
|
|
|
|
*/
|
2019-06-21 16:42:12 +08:00
|
|
|
unsigned long schedutil_cpu_util(int cpu, unsigned long util_cfs,
|
|
|
|
unsigned long max, enum schedutil_type type,
|
|
|
|
struct task_struct *p)
|
2016-08-17 04:14:55 +08:00
|
|
|
{
|
sched/cpufreq: Prepare schedutil for Energy Aware Scheduling
Schedutil requests frequency by aggregating utilization signals from
the scheduler (CFS, RT, DL, IRQ) and applying a 25% margin on top of
them. Since Energy Aware Scheduling (EAS) needs to be able to predict
the frequency requests, it needs to forecast the decisions made by the
governor.
In order to prepare the introduction of EAS, introduce
schedutil_freq_util() to centralize the aforementioned signal
aggregation and make it available to both schedutil and EAS. Since
frequency selection and energy estimation still need to deal with RT and
DL signals slightly differently, schedutil_freq_util() is called with a
different 'type' parameter in those two contexts, and returns an
aggregated utilization signal accordingly. While at it, introduce the
map_util_freq() function which is designed to make schedutil's 25%
margin usable easily for both sugov and EAS.
As EAS will be able to predict schedutil's frequency requests more
accurately than any other governor by design, it'd be sensible to make
sure EAS cannot be used without schedutil. This will be done later, once
EAS has actually been introduced.
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Quentin Perret <quentin.perret@arm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: adharmap@codeaurora.org
Cc: chris.redpath@arm.com
Cc: currojerez@riseup.net
Cc: dietmar.eggemann@arm.com
Cc: edubezval@gmail.com
Cc: gregkh@linuxfoundation.org
Cc: javi.merino@kernel.org
Cc: joel@joelfernandes.org
Cc: juri.lelli@redhat.com
Cc: morten.rasmussen@arm.com
Cc: patrick.bellasi@arm.com
Cc: pkondeti@codeaurora.org
Cc: rjw@rjwysocki.net
Cc: skannan@codeaurora.org
Cc: smuckle@google.com
Cc: srinivas.pandruvada@linux.intel.com
Cc: thara.gopinath@linaro.org
Cc: tkjos@google.com
Cc: valentin.schneider@arm.com
Cc: vincent.guittot@linaro.org
Cc: viresh.kumar@linaro.org
Link: https://lkml.kernel.org/r/20181203095628.11858-3-quentin.perret@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-12-03 17:56:15 +08:00
|
|
|
unsigned long dl_util, util, irq;
|
|
|
|
struct rq *rq = cpu_rq(cpu);
|
2017-12-20 23:26:12 +08:00
|
|
|
|
2020-06-30 19:21:23 +08:00
|
|
|
if (!uclamp_is_used() &&
|
2019-06-21 16:42:10 +08:00
|
|
|
type == FREQUENCY_UTIL && rt_rq_is_runnable(&rq->rt)) {
|
2018-06-28 23:45:11 +08:00
|
|
|
return max;
|
2019-06-21 16:42:10 +08:00
|
|
|
}
|
2018-06-28 23:45:11 +08:00
|
|
|
|
2018-07-05 20:36:17 +08:00
|
|
|
/*
|
|
|
|
* Early check to see if IRQ/steal time saturates the CPU, can be
|
|
|
|
* because of inaccuracies in how we track these -- see
|
|
|
|
* update_irq_load_avg().
|
|
|
|
*/
|
2018-06-28 23:45:11 +08:00
|
|
|
irq = cpu_util_irq(rq);
|
|
|
|
if (unlikely(irq >= max))
|
2018-06-28 23:45:10 +08:00
|
|
|
return max;
|
|
|
|
|
2018-07-05 20:36:17 +08:00
|
|
|
/*
|
|
|
|
* Because the time spend on RT/DL tasks is visible as 'lost' time to
|
|
|
|
* CFS tasks and we use the same metric to track the effective
|
|
|
|
* utilization (PELT windows are synchronized) we can directly add them
|
|
|
|
* to obtain the CPU's actual utilization.
|
2019-06-21 16:42:10 +08:00
|
|
|
*
|
|
|
|
* CFS and RT utilization can be boosted or capped, depending on
|
|
|
|
* utilization clamp constraints requested by currently RUNNABLE
|
|
|
|
* tasks.
|
|
|
|
* When there are no CFS RUNNABLE tasks, clamps are released and
|
|
|
|
* frequency will be gracefully reduced with the utilization decay.
|
2018-07-05 20:36:17 +08:00
|
|
|
*/
|
2019-06-21 16:42:10 +08:00
|
|
|
util = util_cfs + cpu_util_rt(rq);
|
|
|
|
if (type == FREQUENCY_UTIL)
|
2019-12-11 19:38:49 +08:00
|
|
|
util = uclamp_rq_util_with(rq, util, p);
|
2018-06-28 23:45:06 +08:00
|
|
|
|
sched/cpufreq: Prepare schedutil for Energy Aware Scheduling
Schedutil requests frequency by aggregating utilization signals from
the scheduler (CFS, RT, DL, IRQ) and applying a 25% margin on top of
them. Since Energy Aware Scheduling (EAS) needs to be able to predict
the frequency requests, it needs to forecast the decisions made by the
governor.
In order to prepare the introduction of EAS, introduce
schedutil_freq_util() to centralize the aforementioned signal
aggregation and make it available to both schedutil and EAS. Since
frequency selection and energy estimation still need to deal with RT and
DL signals slightly differently, schedutil_freq_util() is called with a
different 'type' parameter in those two contexts, and returns an
aggregated utilization signal accordingly. While at it, introduce the
map_util_freq() function which is designed to make schedutil's 25%
margin usable easily for both sugov and EAS.
As EAS will be able to predict schedutil's frequency requests more
accurately than any other governor by design, it'd be sensible to make
sure EAS cannot be used without schedutil. This will be done later, once
EAS has actually been introduced.
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Quentin Perret <quentin.perret@arm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: adharmap@codeaurora.org
Cc: chris.redpath@arm.com
Cc: currojerez@riseup.net
Cc: dietmar.eggemann@arm.com
Cc: edubezval@gmail.com
Cc: gregkh@linuxfoundation.org
Cc: javi.merino@kernel.org
Cc: joel@joelfernandes.org
Cc: juri.lelli@redhat.com
Cc: morten.rasmussen@arm.com
Cc: patrick.bellasi@arm.com
Cc: pkondeti@codeaurora.org
Cc: rjw@rjwysocki.net
Cc: skannan@codeaurora.org
Cc: smuckle@google.com
Cc: srinivas.pandruvada@linux.intel.com
Cc: thara.gopinath@linaro.org
Cc: tkjos@google.com
Cc: valentin.schneider@arm.com
Cc: vincent.guittot@linaro.org
Cc: viresh.kumar@linaro.org
Link: https://lkml.kernel.org/r/20181203095628.11858-3-quentin.perret@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-12-03 17:56:15 +08:00
|
|
|
dl_util = cpu_util_dl(rq);
|
|
|
|
|
2018-06-28 23:45:10 +08:00
|
|
|
/*
|
sched/cpufreq: Prepare schedutil for Energy Aware Scheduling
Schedutil requests frequency by aggregating utilization signals from
the scheduler (CFS, RT, DL, IRQ) and applying a 25% margin on top of
them. Since Energy Aware Scheduling (EAS) needs to be able to predict
the frequency requests, it needs to forecast the decisions made by the
governor.
In order to prepare the introduction of EAS, introduce
schedutil_freq_util() to centralize the aforementioned signal
aggregation and make it available to both schedutil and EAS. Since
frequency selection and energy estimation still need to deal with RT and
DL signals slightly differently, schedutil_freq_util() is called with a
different 'type' parameter in those two contexts, and returns an
aggregated utilization signal accordingly. While at it, introduce the
map_util_freq() function which is designed to make schedutil's 25%
margin usable easily for both sugov and EAS.
As EAS will be able to predict schedutil's frequency requests more
accurately than any other governor by design, it'd be sensible to make
sure EAS cannot be used without schedutil. This will be done later, once
EAS has actually been introduced.
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Quentin Perret <quentin.perret@arm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: adharmap@codeaurora.org
Cc: chris.redpath@arm.com
Cc: currojerez@riseup.net
Cc: dietmar.eggemann@arm.com
Cc: edubezval@gmail.com
Cc: gregkh@linuxfoundation.org
Cc: javi.merino@kernel.org
Cc: joel@joelfernandes.org
Cc: juri.lelli@redhat.com
Cc: morten.rasmussen@arm.com
Cc: patrick.bellasi@arm.com
Cc: pkondeti@codeaurora.org
Cc: rjw@rjwysocki.net
Cc: skannan@codeaurora.org
Cc: smuckle@google.com
Cc: srinivas.pandruvada@linux.intel.com
Cc: thara.gopinath@linaro.org
Cc: tkjos@google.com
Cc: valentin.schneider@arm.com
Cc: vincent.guittot@linaro.org
Cc: viresh.kumar@linaro.org
Link: https://lkml.kernel.org/r/20181203095628.11858-3-quentin.perret@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-12-03 17:56:15 +08:00
|
|
|
* For frequency selection we do not make cpu_util_dl() a permanent part
|
|
|
|
* of this sum because we want to use cpu_bw_dl() later on, but we need
|
|
|
|
* to check if the CFS+RT+DL sum is saturated (ie. no idle time) such
|
|
|
|
* that we select f_max when there is no idle time.
|
2018-07-05 20:36:17 +08:00
|
|
|
*
|
|
|
|
* NOTE: numerical errors or stop class might cause us to not quite hit
|
|
|
|
* saturation when we should -- something for later.
|
2018-06-28 23:45:10 +08:00
|
|
|
*/
|
sched/cpufreq: Prepare schedutil for Energy Aware Scheduling
Schedutil requests frequency by aggregating utilization signals from
the scheduler (CFS, RT, DL, IRQ) and applying a 25% margin on top of
them. Since Energy Aware Scheduling (EAS) needs to be able to predict
the frequency requests, it needs to forecast the decisions made by the
governor.
In order to prepare the introduction of EAS, introduce
schedutil_freq_util() to centralize the aforementioned signal
aggregation and make it available to both schedutil and EAS. Since
frequency selection and energy estimation still need to deal with RT and
DL signals slightly differently, schedutil_freq_util() is called with a
different 'type' parameter in those two contexts, and returns an
aggregated utilization signal accordingly. While at it, introduce the
map_util_freq() function which is designed to make schedutil's 25%
margin usable easily for both sugov and EAS.
As EAS will be able to predict schedutil's frequency requests more
accurately than any other governor by design, it'd be sensible to make
sure EAS cannot be used without schedutil. This will be done later, once
EAS has actually been introduced.
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Quentin Perret <quentin.perret@arm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: adharmap@codeaurora.org
Cc: chris.redpath@arm.com
Cc: currojerez@riseup.net
Cc: dietmar.eggemann@arm.com
Cc: edubezval@gmail.com
Cc: gregkh@linuxfoundation.org
Cc: javi.merino@kernel.org
Cc: joel@joelfernandes.org
Cc: juri.lelli@redhat.com
Cc: morten.rasmussen@arm.com
Cc: patrick.bellasi@arm.com
Cc: pkondeti@codeaurora.org
Cc: rjw@rjwysocki.net
Cc: skannan@codeaurora.org
Cc: smuckle@google.com
Cc: srinivas.pandruvada@linux.intel.com
Cc: thara.gopinath@linaro.org
Cc: tkjos@google.com
Cc: valentin.schneider@arm.com
Cc: vincent.guittot@linaro.org
Cc: viresh.kumar@linaro.org
Link: https://lkml.kernel.org/r/20181203095628.11858-3-quentin.perret@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-12-03 17:56:15 +08:00
|
|
|
if (util + dl_util >= max)
|
2018-06-28 23:45:10 +08:00
|
|
|
return max;
|
2018-06-28 23:45:08 +08:00
|
|
|
|
sched/cpufreq: Prepare schedutil for Energy Aware Scheduling
Schedutil requests frequency by aggregating utilization signals from
the scheduler (CFS, RT, DL, IRQ) and applying a 25% margin on top of
them. Since Energy Aware Scheduling (EAS) needs to be able to predict
the frequency requests, it needs to forecast the decisions made by the
governor.
In order to prepare the introduction of EAS, introduce
schedutil_freq_util() to centralize the aforementioned signal
aggregation and make it available to both schedutil and EAS. Since
frequency selection and energy estimation still need to deal with RT and
DL signals slightly differently, schedutil_freq_util() is called with a
different 'type' parameter in those two contexts, and returns an
aggregated utilization signal accordingly. While at it, introduce the
map_util_freq() function which is designed to make schedutil's 25%
margin usable easily for both sugov and EAS.
As EAS will be able to predict schedutil's frequency requests more
accurately than any other governor by design, it'd be sensible to make
sure EAS cannot be used without schedutil. This will be done later, once
EAS has actually been introduced.
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Quentin Perret <quentin.perret@arm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: adharmap@codeaurora.org
Cc: chris.redpath@arm.com
Cc: currojerez@riseup.net
Cc: dietmar.eggemann@arm.com
Cc: edubezval@gmail.com
Cc: gregkh@linuxfoundation.org
Cc: javi.merino@kernel.org
Cc: joel@joelfernandes.org
Cc: juri.lelli@redhat.com
Cc: morten.rasmussen@arm.com
Cc: patrick.bellasi@arm.com
Cc: pkondeti@codeaurora.org
Cc: rjw@rjwysocki.net
Cc: skannan@codeaurora.org
Cc: smuckle@google.com
Cc: srinivas.pandruvada@linux.intel.com
Cc: thara.gopinath@linaro.org
Cc: tkjos@google.com
Cc: valentin.schneider@arm.com
Cc: vincent.guittot@linaro.org
Cc: viresh.kumar@linaro.org
Link: https://lkml.kernel.org/r/20181203095628.11858-3-quentin.perret@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-12-03 17:56:15 +08:00
|
|
|
/*
|
|
|
|
* OTOH, for energy computation we need the estimated running time, so
|
|
|
|
* include util_dl and ignore dl_bw.
|
|
|
|
*/
|
|
|
|
if (type == ENERGY_UTIL)
|
|
|
|
util += dl_util;
|
|
|
|
|
2017-12-04 18:23:18 +08:00
|
|
|
/*
|
2018-07-05 20:36:17 +08:00
|
|
|
* There is still idle time; further improve the number by using the
|
|
|
|
* irq metric. Because IRQ/steal time is hidden from the task clock we
|
|
|
|
* need to scale the task numbers:
|
2018-06-28 23:45:08 +08:00
|
|
|
*
|
2019-08-02 18:46:28 +08:00
|
|
|
* max - irq
|
|
|
|
* U' = irq + --------- * U
|
|
|
|
* max
|
2018-07-05 20:36:17 +08:00
|
|
|
*/
|
2018-07-19 20:00:06 +08:00
|
|
|
util = scale_irq_capacity(util, irq, max);
|
2018-07-05 20:36:17 +08:00
|
|
|
util += irq;
|
|
|
|
|
|
|
|
/*
|
2018-06-28 23:45:08 +08:00
|
|
|
* Bandwidth required by DEADLINE must always be granted while, for
|
|
|
|
* FAIR and RT, we use blocked utilization of IDLE CPUs as a mechanism
|
|
|
|
* to gracefully reduce the frequency when no tasks show up for longer
|
2018-05-24 22:10:22 +08:00
|
|
|
* periods of time.
|
|
|
|
*
|
2018-07-05 20:36:17 +08:00
|
|
|
* Ideally we would like to set bw_dl as min/guaranteed freq and util +
|
|
|
|
* bw_dl as requested freq. However, cpufreq is not yet ready for such
|
|
|
|
* an interface. So, we only do the latter for now.
|
2017-12-04 18:23:18 +08:00
|
|
|
*/
|
sched/cpufreq: Prepare schedutil for Energy Aware Scheduling
Schedutil requests frequency by aggregating utilization signals from
the scheduler (CFS, RT, DL, IRQ) and applying a 25% margin on top of
them. Since Energy Aware Scheduling (EAS) needs to be able to predict
the frequency requests, it needs to forecast the decisions made by the
governor.
In order to prepare the introduction of EAS, introduce
schedutil_freq_util() to centralize the aforementioned signal
aggregation and make it available to both schedutil and EAS. Since
frequency selection and energy estimation still need to deal with RT and
DL signals slightly differently, schedutil_freq_util() is called with a
different 'type' parameter in those two contexts, and returns an
aggregated utilization signal accordingly. While at it, introduce the
map_util_freq() function which is designed to make schedutil's 25%
margin usable easily for both sugov and EAS.
As EAS will be able to predict schedutil's frequency requests more
accurately than any other governor by design, it'd be sensible to make
sure EAS cannot be used without schedutil. This will be done later, once
EAS has actually been introduced.
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Quentin Perret <quentin.perret@arm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: adharmap@codeaurora.org
Cc: chris.redpath@arm.com
Cc: currojerez@riseup.net
Cc: dietmar.eggemann@arm.com
Cc: edubezval@gmail.com
Cc: gregkh@linuxfoundation.org
Cc: javi.merino@kernel.org
Cc: joel@joelfernandes.org
Cc: juri.lelli@redhat.com
Cc: morten.rasmussen@arm.com
Cc: patrick.bellasi@arm.com
Cc: pkondeti@codeaurora.org
Cc: rjw@rjwysocki.net
Cc: skannan@codeaurora.org
Cc: smuckle@google.com
Cc: srinivas.pandruvada@linux.intel.com
Cc: thara.gopinath@linaro.org
Cc: tkjos@google.com
Cc: valentin.schneider@arm.com
Cc: vincent.guittot@linaro.org
Cc: viresh.kumar@linaro.org
Link: https://lkml.kernel.org/r/20181203095628.11858-3-quentin.perret@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-12-03 17:56:15 +08:00
|
|
|
if (type == FREQUENCY_UTIL)
|
|
|
|
util += cpu_bw_dl(rq);
|
|
|
|
|
|
|
|
return min(max, util);
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu)
|
|
|
|
{
|
|
|
|
struct rq *rq = cpu_rq(sg_cpu->cpu);
|
|
|
|
unsigned long util = cpu_util_cfs(rq);
|
2019-06-17 23:00:17 +08:00
|
|
|
unsigned long max = arch_scale_cpu_capacity(sg_cpu->cpu);
|
sched/cpufreq: Prepare schedutil for Energy Aware Scheduling
Schedutil requests frequency by aggregating utilization signals from
the scheduler (CFS, RT, DL, IRQ) and applying a 25% margin on top of
them. Since Energy Aware Scheduling (EAS) needs to be able to predict
the frequency requests, it needs to forecast the decisions made by the
governor.
In order to prepare the introduction of EAS, introduce
schedutil_freq_util() to centralize the aforementioned signal
aggregation and make it available to both schedutil and EAS. Since
frequency selection and energy estimation still need to deal with RT and
DL signals slightly differently, schedutil_freq_util() is called with a
different 'type' parameter in those two contexts, and returns an
aggregated utilization signal accordingly. While at it, introduce the
map_util_freq() function which is designed to make schedutil's 25%
margin usable easily for both sugov and EAS.
As EAS will be able to predict schedutil's frequency requests more
accurately than any other governor by design, it'd be sensible to make
sure EAS cannot be used without schedutil. This will be done later, once
EAS has actually been introduced.
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Quentin Perret <quentin.perret@arm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: adharmap@codeaurora.org
Cc: chris.redpath@arm.com
Cc: currojerez@riseup.net
Cc: dietmar.eggemann@arm.com
Cc: edubezval@gmail.com
Cc: gregkh@linuxfoundation.org
Cc: javi.merino@kernel.org
Cc: joel@joelfernandes.org
Cc: juri.lelli@redhat.com
Cc: morten.rasmussen@arm.com
Cc: patrick.bellasi@arm.com
Cc: pkondeti@codeaurora.org
Cc: rjw@rjwysocki.net
Cc: skannan@codeaurora.org
Cc: smuckle@google.com
Cc: srinivas.pandruvada@linux.intel.com
Cc: thara.gopinath@linaro.org
Cc: tkjos@google.com
Cc: valentin.schneider@arm.com
Cc: vincent.guittot@linaro.org
Cc: viresh.kumar@linaro.org
Link: https://lkml.kernel.org/r/20181203095628.11858-3-quentin.perret@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-12-03 17:56:15 +08:00
|
|
|
|
|
|
|
sg_cpu->max = max;
|
|
|
|
sg_cpu->bw_dl = cpu_bw_dl(rq);
|
|
|
|
|
2019-06-21 16:42:12 +08:00
|
|
|
return schedutil_cpu_util(sg_cpu->cpu, util, max, FREQUENCY_UTIL, NULL);
|
2016-08-17 04:14:55 +08:00
|
|
|
}
|
|
|
|
|
2018-05-22 19:07:54 +08:00
|
|
|
/**
|
|
|
|
* sugov_iowait_reset() - Reset the IO boost status of a CPU.
|
|
|
|
* @sg_cpu: the sugov data for the CPU to boost
|
|
|
|
* @time: the update time from the caller
|
|
|
|
* @set_iowait_boost: true if an IO boost has been requested
|
|
|
|
*
|
|
|
|
* The IO wait boost of a task is disabled after a tick since the last update
|
|
|
|
* of a CPU. If a new IO wait boost is requested after more then a tick, then
|
2019-03-28 18:33:21 +08:00
|
|
|
* we enable the boost starting from IOWAIT_BOOST_MIN, which improves energy
|
|
|
|
* efficiency by ignoring sporadic wakeups from IO.
|
2018-05-22 19:07:54 +08:00
|
|
|
*/
|
|
|
|
static bool sugov_iowait_reset(struct sugov_cpu *sg_cpu, u64 time,
|
|
|
|
bool set_iowait_boost)
|
2016-09-10 06:00:31 +08:00
|
|
|
{
|
2018-05-22 19:07:54 +08:00
|
|
|
s64 delta_ns = time - sg_cpu->last_update;
|
2017-07-23 23:54:25 +08:00
|
|
|
|
2018-05-22 19:07:54 +08:00
|
|
|
/* Reset boost only if a tick has elapsed since last request */
|
|
|
|
if (delta_ns <= TICK_NSEC)
|
|
|
|
return false;
|
2017-07-23 23:54:25 +08:00
|
|
|
|
2019-03-28 18:33:21 +08:00
|
|
|
sg_cpu->iowait_boost = set_iowait_boost ? IOWAIT_BOOST_MIN : 0;
|
2018-05-22 19:07:54 +08:00
|
|
|
sg_cpu->iowait_boost_pending = set_iowait_boost;
|
2016-09-10 06:00:31 +08:00
|
|
|
|
2018-05-22 19:07:54 +08:00
|
|
|
return true;
|
|
|
|
}
|
2017-07-23 23:54:25 +08:00
|
|
|
|
2018-05-22 19:07:54 +08:00
|
|
|
/**
|
|
|
|
* sugov_iowait_boost() - Updates the IO boost status of a CPU.
|
|
|
|
* @sg_cpu: the sugov data for the CPU to boost
|
|
|
|
* @time: the update time from the caller
|
|
|
|
* @flags: SCHED_CPUFREQ_IOWAIT if the task is waking up after an IO wait
|
|
|
|
*
|
|
|
|
* Each time a task wakes up after an IO operation, the CPU utilization can be
|
|
|
|
* boosted to a certain utilization which doubles at each "frequent and
|
2019-03-28 18:33:21 +08:00
|
|
|
* successive" wakeup from IO, ranging from IOWAIT_BOOST_MIN to the utilization
|
|
|
|
* of the maximum OPP.
|
|
|
|
*
|
2018-05-22 19:07:54 +08:00
|
|
|
* To keep doubling, an IO boost has to be requested at least once per tick,
|
|
|
|
* otherwise we restart from the utilization of the minimum OPP.
|
|
|
|
*/
|
|
|
|
static void sugov_iowait_boost(struct sugov_cpu *sg_cpu, u64 time,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
bool set_iowait_boost = flags & SCHED_CPUFREQ_IOWAIT;
|
|
|
|
|
|
|
|
/* Reset boost if the CPU appears to have been idle enough */
|
|
|
|
if (sg_cpu->iowait_boost &&
|
|
|
|
sugov_iowait_reset(sg_cpu, time, set_iowait_boost))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Boost only tasks waking up after IO */
|
|
|
|
if (!set_iowait_boost)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Ensure boost doubles only one time at each request */
|
|
|
|
if (sg_cpu->iowait_boost_pending)
|
|
|
|
return;
|
|
|
|
sg_cpu->iowait_boost_pending = true;
|
|
|
|
|
|
|
|
/* Double the boost at each request */
|
|
|
|
if (sg_cpu->iowait_boost) {
|
2019-03-05 16:32:02 +08:00
|
|
|
sg_cpu->iowait_boost =
|
|
|
|
min_t(unsigned int, sg_cpu->iowait_boost << 1, SCHED_CAPACITY_SCALE);
|
2018-05-22 19:07:54 +08:00
|
|
|
return;
|
2016-09-10 06:00:31 +08:00
|
|
|
}
|
2018-05-22 19:07:54 +08:00
|
|
|
|
|
|
|
/* First wakeup after IO: start with minimum boost */
|
2019-03-28 18:33:21 +08:00
|
|
|
sg_cpu->iowait_boost = IOWAIT_BOOST_MIN;
|
2016-09-10 06:00:31 +08:00
|
|
|
}
|
|
|
|
|
2018-05-22 19:07:54 +08:00
|
|
|
/**
|
|
|
|
* sugov_iowait_apply() - Apply the IO boost to a CPU.
|
|
|
|
* @sg_cpu: the sugov data for the cpu to boost
|
|
|
|
* @time: the update time from the caller
|
|
|
|
* @util: the utilization to (eventually) boost
|
|
|
|
* @max: the maximum value the utilization can be boosted to
|
|
|
|
*
|
|
|
|
* A CPU running a task which woken up after an IO operation can have its
|
|
|
|
* utilization boosted to speed up the completion of those IO operations.
|
|
|
|
* The IO boost value is increased each time a task wakes up from IO, in
|
|
|
|
* sugov_iowait_apply(), and it's instead decreased by this function,
|
|
|
|
* each time an increase has not been requested (!iowait_boost_pending).
|
|
|
|
*
|
|
|
|
* A CPU which also appears to have been idle for at least one tick has also
|
|
|
|
* its IO boost utilization reset.
|
|
|
|
*
|
|
|
|
* This mechanism is designed to boost high frequently IO waiting tasks, while
|
|
|
|
* being more conservative on tasks which does sporadic IO operations.
|
|
|
|
*/
|
2019-03-05 16:32:02 +08:00
|
|
|
static unsigned long sugov_iowait_apply(struct sugov_cpu *sg_cpu, u64 time,
|
|
|
|
unsigned long util, unsigned long max)
|
2016-09-10 06:00:31 +08:00
|
|
|
{
|
2019-03-05 16:32:02 +08:00
|
|
|
unsigned long boost;
|
2016-09-10 06:00:31 +08:00
|
|
|
|
2018-05-22 19:07:54 +08:00
|
|
|
/* No boost currently required */
|
2017-07-23 23:54:25 +08:00
|
|
|
if (!sg_cpu->iowait_boost)
|
2019-03-05 16:32:02 +08:00
|
|
|
return util;
|
2016-09-10 06:00:31 +08:00
|
|
|
|
2018-05-22 19:07:54 +08:00
|
|
|
/* Reset boost if the CPU appears to have been idle enough */
|
|
|
|
if (sugov_iowait_reset(sg_cpu, time, false))
|
2019-03-05 16:32:02 +08:00
|
|
|
return util;
|
2018-05-22 19:07:54 +08:00
|
|
|
|
2019-03-05 16:32:02 +08:00
|
|
|
if (!sg_cpu->iowait_boost_pending) {
|
2018-05-22 19:07:54 +08:00
|
|
|
/*
|
2019-03-05 16:32:02 +08:00
|
|
|
* No boost pending; reduce the boost value.
|
2018-05-22 19:07:54 +08:00
|
|
|
*/
|
2017-07-23 23:54:25 +08:00
|
|
|
sg_cpu->iowait_boost >>= 1;
|
2019-03-28 18:33:21 +08:00
|
|
|
if (sg_cpu->iowait_boost < IOWAIT_BOOST_MIN) {
|
2017-07-23 23:54:25 +08:00
|
|
|
sg_cpu->iowait_boost = 0;
|
2019-03-05 16:32:02 +08:00
|
|
|
return util;
|
2017-07-23 23:54:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-05 16:32:02 +08:00
|
|
|
sg_cpu->iowait_boost_pending = false;
|
|
|
|
|
2018-05-22 19:07:54 +08:00
|
|
|
/*
|
2019-03-05 16:32:02 +08:00
|
|
|
* @util is already in capacity scale; convert iowait_boost
|
|
|
|
* into the same scale so we can compare.
|
2018-05-22 19:07:54 +08:00
|
|
|
*/
|
2019-03-05 16:32:02 +08:00
|
|
|
boost = (sg_cpu->iowait_boost * max) >> SCHED_CAPACITY_SHIFT;
|
|
|
|
return max(boost, util);
|
2016-09-10 06:00:31 +08:00
|
|
|
}
|
|
|
|
|
cpufreq: schedutil: Avoid reducing frequency of busy CPUs prematurely
The way the schedutil governor uses the PELT metric causes it to
underestimate the CPU utilization in some cases.
That can be easily demonstrated by running kernel compilation on
a Sandy Bridge Intel processor, running turbostat in parallel with
it and looking at the values written to the MSR_IA32_PERF_CTL
register. Namely, the expected result would be that when all CPUs
were 100% busy, all of them would be requested to run in the maximum
P-state, but observation shows that this clearly isn't the case.
The CPUs run in the maximum P-state for a while and then are
requested to run slower and go back to the maximum P-state after
a while again. That causes the actual frequency of the processor to
visibly oscillate below the sustainable maximum in a jittery fashion
which clearly is not desirable.
That has been attributed to CPU utilization metric updates on task
migration that cause the total utilization value for the CPU to be
reduced by the utilization of the migrated task. If that happens,
the schedutil governor may see a CPU utilization reduction and will
attempt to reduce the CPU frequency accordingly right away. That
may be premature, though, for example if the system is generally
busy and there are other runnable tasks waiting to be run on that
CPU already.
This is unlikely to be an issue on systems where cpufreq policies are
shared between multiple CPUs, because in those cases the policy
utilization is computed as the maximum of the CPU utilization values
over the whole policy and if that turns out to be low, reducing the
frequency for the policy most likely is a good idea anyway. On
systems with one CPU per policy, however, it may affect performance
adversely and even lead to increased energy consumption in some cases.
On those systems it may be addressed by taking another utilization
metric into consideration, like whether or not the CPU whose
frequency is about to be reduced has been idle recently, because if
that's not the case, the CPU is likely to be busy in the near future
and its frequency should not be reduced.
To that end, use the counter of idle calls in the timekeeping code.
Namely, make the schedutil governor look at that counter for the
current CPU every time before its frequency is about to be reduced.
If the counter has not changed since the previous iteration of the
governor computations for that CPU, the CPU has been busy for all
that time and its frequency should not be decreased, so if the new
frequency would be lower than the one set previously, the governor
will skip the frequency update.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Joel Fernandes <joelaf@google.com>
2017-03-22 07:08:50 +08:00
|
|
|
#ifdef CONFIG_NO_HZ_COMMON
|
|
|
|
static bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu)
|
|
|
|
{
|
2017-12-21 09:22:45 +08:00
|
|
|
unsigned long idle_calls = tick_nohz_get_idle_calls_cpu(sg_cpu->cpu);
|
cpufreq: schedutil: Avoid reducing frequency of busy CPUs prematurely
The way the schedutil governor uses the PELT metric causes it to
underestimate the CPU utilization in some cases.
That can be easily demonstrated by running kernel compilation on
a Sandy Bridge Intel processor, running turbostat in parallel with
it and looking at the values written to the MSR_IA32_PERF_CTL
register. Namely, the expected result would be that when all CPUs
were 100% busy, all of them would be requested to run in the maximum
P-state, but observation shows that this clearly isn't the case.
The CPUs run in the maximum P-state for a while and then are
requested to run slower and go back to the maximum P-state after
a while again. That causes the actual frequency of the processor to
visibly oscillate below the sustainable maximum in a jittery fashion
which clearly is not desirable.
That has been attributed to CPU utilization metric updates on task
migration that cause the total utilization value for the CPU to be
reduced by the utilization of the migrated task. If that happens,
the schedutil governor may see a CPU utilization reduction and will
attempt to reduce the CPU frequency accordingly right away. That
may be premature, though, for example if the system is generally
busy and there are other runnable tasks waiting to be run on that
CPU already.
This is unlikely to be an issue on systems where cpufreq policies are
shared between multiple CPUs, because in those cases the policy
utilization is computed as the maximum of the CPU utilization values
over the whole policy and if that turns out to be low, reducing the
frequency for the policy most likely is a good idea anyway. On
systems with one CPU per policy, however, it may affect performance
adversely and even lead to increased energy consumption in some cases.
On those systems it may be addressed by taking another utilization
metric into consideration, like whether or not the CPU whose
frequency is about to be reduced has been idle recently, because if
that's not the case, the CPU is likely to be busy in the near future
and its frequency should not be reduced.
To that end, use the counter of idle calls in the timekeeping code.
Namely, make the schedutil governor look at that counter for the
current CPU every time before its frequency is about to be reduced.
If the counter has not changed since the previous iteration of the
governor computations for that CPU, the CPU has been busy for all
that time and its frequency should not be decreased, so if the new
frequency would be lower than the one set previously, the governor
will skip the frequency update.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Joel Fernandes <joelaf@google.com>
2017-03-22 07:08:50 +08:00
|
|
|
bool ret = idle_calls == sg_cpu->saved_idle_calls;
|
|
|
|
|
|
|
|
sg_cpu->saved_idle_calls = idle_calls;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; }
|
|
|
|
#endif /* CONFIG_NO_HZ_COMMON */
|
|
|
|
|
2018-03-13 18:35:40 +08:00
|
|
|
/*
|
|
|
|
* Make sugov_should_update_freq() ignore the rate limit when DL
|
|
|
|
* has increased the utilization.
|
|
|
|
*/
|
|
|
|
static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu, struct sugov_policy *sg_policy)
|
|
|
|
{
|
2018-06-28 23:45:08 +08:00
|
|
|
if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl)
|
2019-08-07 15:06:01 +08:00
|
|
|
sg_policy->limits_changed = true;
|
2018-03-13 18:35:40 +08:00
|
|
|
}
|
|
|
|
|
2016-04-02 07:09:12 +08:00
|
|
|
static void sugov_update_single(struct update_util_data *hook, u64 time,
|
2016-08-17 04:14:55 +08:00
|
|
|
unsigned int flags)
|
2016-04-02 07:09:12 +08:00
|
|
|
{
|
|
|
|
struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util);
|
|
|
|
struct sugov_policy *sg_policy = sg_cpu->sg_policy;
|
2016-08-17 04:14:55 +08:00
|
|
|
unsigned long util, max;
|
2016-04-02 07:09:12 +08:00
|
|
|
unsigned int next_f;
|
2020-10-17 02:17:22 +08:00
|
|
|
unsigned int cached_freq = sg_policy->cached_raw_freq;
|
2016-04-02 07:09:12 +08:00
|
|
|
|
2018-05-22 19:07:54 +08:00
|
|
|
sugov_iowait_boost(sg_cpu, time, flags);
|
2016-09-10 06:00:31 +08:00
|
|
|
sg_cpu->last_update = time;
|
|
|
|
|
2018-03-13 18:35:40 +08:00
|
|
|
ignore_dl_rate_limit(sg_cpu, sg_policy);
|
|
|
|
|
2016-04-02 07:09:12 +08:00
|
|
|
if (!sugov_should_update_freq(sg_policy, time))
|
|
|
|
return;
|
|
|
|
|
2018-06-28 23:45:11 +08:00
|
|
|
util = sugov_get_util(sg_cpu);
|
2017-12-20 23:26:12 +08:00
|
|
|
max = sg_cpu->max;
|
2019-03-05 16:32:02 +08:00
|
|
|
util = sugov_iowait_apply(sg_cpu, time, util, max);
|
2017-12-20 23:26:12 +08:00
|
|
|
next_f = get_next_freq(sg_policy, util, max);
|
|
|
|
/*
|
|
|
|
* Do not reduce the frequency if the CPU has not been idle
|
|
|
|
* recently, as the reduction is likely to be premature then.
|
|
|
|
*/
|
cpufreq: schedutil: Don't skip freq update if need_freq_update is set
The cpufreq policy's frequency limits (min/max) can get changed at any
point of time, while schedutil is trying to update the next frequency.
Though the schedutil governor has necessary locking and support in place
to make sure we don't miss any of those updates, there is a corner case
where the governor will find that the CPU is already running at the
desired frequency and so may skip an update.
For example, consider that the CPU can run at 1 GHz, 1.2 GHz and 1.4 GHz
and is running at 1 GHz currently. Schedutil tries to update the
frequency to 1.2 GHz, during this time the policy limits get changed as
policy->min = 1.4 GHz. As schedutil (and cpufreq core) does clamp the
frequency at various instances, we will eventually set the frequency to
1.4 GHz, while we will save 1.2 GHz in sg_policy->next_freq.
Now lets say the policy limits get changed back at this time with
policy->min as 1 GHz. The next time schedutil is invoked by the
scheduler, we will reevaluate the next frequency (because
need_freq_update will get set due to limits change event) and lets say
we want to set the frequency to 1.2 GHz again. At this point
sugov_update_next_freq() will find the next_freq == current_freq and
will abort the update, while the CPU actually runs at 1.4 GHz.
Until now need_freq_update was used as a flag to indicate that the
policy's frequency limits have changed, and that we should consider the
new limits while reevaluating the next frequency.
This patch fixes the above mentioned issue by extending the purpose of
the need_freq_update flag. If this flag is set now, the schedutil
governor will not try to abort a frequency change even if next_freq ==
current_freq.
As similar behavior is required in the case of
CPUFREQ_NEED_UPDATE_LIMITS flag as well, need_freq_update will never be
set to false if that flag is set for the driver.
We also don't need to consider the need_freq_update flag in
sugov_update_single() anymore to handle the special case of busy CPU, as
we won't abort a frequency update anymore.
Reported-by: zhuguangqing <zhuguangqing@xiaomi.com>
Suggested-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
[ rjw: Rearrange code to avoid a branch ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2020-10-30 15:21:08 +08:00
|
|
|
if (sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
|
2017-12-20 23:26:12 +08:00
|
|
|
next_f = sg_policy->next_freq;
|
2017-11-08 22:53:55 +08:00
|
|
|
|
2020-10-17 02:17:22 +08:00
|
|
|
/* Restore cached freq as next_freq has changed */
|
|
|
|
sg_policy->cached_raw_freq = cached_freq;
|
2016-08-17 04:14:55 +08:00
|
|
|
}
|
2017-12-20 23:26:12 +08:00
|
|
|
|
2018-05-23 17:47:45 +08:00
|
|
|
/*
|
|
|
|
* This code runs under rq->lock for the target CPU, so it won't run
|
|
|
|
* concurrently on two different CPUs for the same target and it is not
|
|
|
|
* necessary to acquire the lock in the fast switch case.
|
|
|
|
*/
|
|
|
|
if (sg_policy->policy->fast_switch_enabled) {
|
|
|
|
sugov_fast_switch(sg_policy, time, next_f);
|
|
|
|
} else {
|
|
|
|
raw_spin_lock(&sg_policy->update_lock);
|
|
|
|
sugov_deferred_update(sg_policy, time, next_f);
|
|
|
|
raw_spin_unlock(&sg_policy->update_lock);
|
|
|
|
}
|
2016-04-02 07:09:12 +08:00
|
|
|
}
|
|
|
|
|
2017-05-03 21:30:48 +08:00
|
|
|
static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, u64 time)
|
2016-04-02 07:09:12 +08:00
|
|
|
{
|
2016-07-14 04:25:26 +08:00
|
|
|
struct sugov_policy *sg_policy = sg_cpu->sg_policy;
|
2016-04-02 07:09:12 +08:00
|
|
|
struct cpufreq_policy *policy = sg_policy->policy;
|
2017-03-09 12:04:54 +08:00
|
|
|
unsigned long util = 0, max = 1;
|
2016-04-02 07:09:12 +08:00
|
|
|
unsigned int j;
|
|
|
|
|
|
|
|
for_each_cpu(j, policy->cpus) {
|
2017-03-09 12:04:54 +08:00
|
|
|
struct sugov_cpu *j_sg_cpu = &per_cpu(sugov_cpu, j);
|
2016-04-02 07:09:12 +08:00
|
|
|
unsigned long j_util, j_max;
|
|
|
|
|
2018-06-28 23:45:11 +08:00
|
|
|
j_util = sugov_get_util(j_sg_cpu);
|
2016-04-02 07:09:12 +08:00
|
|
|
j_max = j_sg_cpu->max;
|
2019-03-05 16:32:02 +08:00
|
|
|
j_util = sugov_iowait_apply(j_sg_cpu, time, j_util, j_max);
|
2018-05-22 19:07:54 +08:00
|
|
|
|
2016-04-02 07:09:12 +08:00
|
|
|
if (j_util * max > j_max * util) {
|
|
|
|
util = j_util;
|
|
|
|
max = j_max;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-02 16:33:21 +08:00
|
|
|
return get_next_freq(sg_policy, util, max);
|
2016-04-02 07:09:12 +08:00
|
|
|
}
|
|
|
|
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
static void
|
|
|
|
sugov_update_shared(struct update_util_data *hook, u64 time, unsigned int flags)
|
2016-04-02 07:09:12 +08:00
|
|
|
{
|
|
|
|
struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util);
|
|
|
|
struct sugov_policy *sg_policy = sg_cpu->sg_policy;
|
|
|
|
unsigned int next_f;
|
|
|
|
|
|
|
|
raw_spin_lock(&sg_policy->update_lock);
|
|
|
|
|
2018-05-22 19:07:54 +08:00
|
|
|
sugov_iowait_boost(sg_cpu, time, flags);
|
2016-04-02 07:09:12 +08:00
|
|
|
sg_cpu->last_update = time;
|
|
|
|
|
2018-03-13 18:35:40 +08:00
|
|
|
ignore_dl_rate_limit(sg_cpu, sg_policy);
|
2017-03-09 12:04:54 +08:00
|
|
|
|
2016-04-02 07:09:12 +08:00
|
|
|
if (sugov_should_update_freq(sg_policy, time)) {
|
2017-12-20 23:26:12 +08:00
|
|
|
next_f = sugov_next_freq_shared(sg_cpu, time);
|
2018-05-23 17:47:45 +08:00
|
|
|
|
|
|
|
if (sg_policy->policy->fast_switch_enabled)
|
|
|
|
sugov_fast_switch(sg_policy, time, next_f);
|
|
|
|
else
|
|
|
|
sugov_deferred_update(sg_policy, time, next_f);
|
2016-04-02 07:09:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
raw_spin_unlock(&sg_policy->update_lock);
|
|
|
|
}
|
|
|
|
|
2016-11-15 16:23:22 +08:00
|
|
|
static void sugov_work(struct kthread_work *work)
|
2016-04-02 07:09:12 +08:00
|
|
|
{
|
|
|
|
struct sugov_policy *sg_policy = container_of(work, struct sugov_policy, work);
|
2018-05-23 06:55:53 +08:00
|
|
|
unsigned int freq;
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Hold sg_policy->update_lock shortly to handle the case where:
|
|
|
|
* incase sg_policy->next_freq is read here, and then updated by
|
2018-05-23 17:47:45 +08:00
|
|
|
* sugov_deferred_update() just before work_in_progress is set to false
|
2018-05-23 06:55:53 +08:00
|
|
|
* here, we may miss queueing the new update.
|
|
|
|
*
|
|
|
|
* Note: If a work was queued after the update_lock is released,
|
2018-05-23 17:47:45 +08:00
|
|
|
* sugov_work() will just be called again by kthread_work code; and the
|
2018-05-23 06:55:53 +08:00
|
|
|
* request will be proceed before the sugov thread sleeps.
|
|
|
|
*/
|
|
|
|
raw_spin_lock_irqsave(&sg_policy->update_lock, flags);
|
|
|
|
freq = sg_policy->next_freq;
|
|
|
|
sg_policy->work_in_progress = false;
|
|
|
|
raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags);
|
2016-04-02 07:09:12 +08:00
|
|
|
|
|
|
|
mutex_lock(&sg_policy->work_lock);
|
2018-05-23 06:55:53 +08:00
|
|
|
__cpufreq_driver_target(sg_policy->policy, freq, CPUFREQ_RELATION_L);
|
2016-04-02 07:09:12 +08:00
|
|
|
mutex_unlock(&sg_policy->work_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sugov_irq_work(struct irq_work *irq_work)
|
|
|
|
{
|
|
|
|
struct sugov_policy *sg_policy;
|
|
|
|
|
|
|
|
sg_policy = container_of(irq_work, struct sugov_policy, irq_work);
|
2016-11-15 16:23:22 +08:00
|
|
|
|
|
|
|
kthread_queue_work(&sg_policy->worker, &sg_policy->work);
|
2016-04-02 07:09:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************** sysfs interface ************************/
|
|
|
|
|
|
|
|
static struct sugov_tunables *global_tunables;
|
|
|
|
static DEFINE_MUTEX(global_tunables_lock);
|
|
|
|
|
|
|
|
static inline struct sugov_tunables *to_sugov_tunables(struct gov_attr_set *attr_set)
|
|
|
|
{
|
|
|
|
return container_of(attr_set, struct sugov_tunables, attr_set);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t rate_limit_us_show(struct gov_attr_set *attr_set, char *buf)
|
|
|
|
{
|
|
|
|
struct sugov_tunables *tunables = to_sugov_tunables(attr_set);
|
|
|
|
|
|
|
|
return sprintf(buf, "%u\n", tunables->rate_limit_us);
|
|
|
|
}
|
|
|
|
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
static ssize_t
|
|
|
|
rate_limit_us_store(struct gov_attr_set *attr_set, const char *buf, size_t count)
|
2016-04-02 07:09:12 +08:00
|
|
|
{
|
|
|
|
struct sugov_tunables *tunables = to_sugov_tunables(attr_set);
|
|
|
|
struct sugov_policy *sg_policy;
|
|
|
|
unsigned int rate_limit_us;
|
|
|
|
|
|
|
|
if (kstrtouint(buf, 10, &rate_limit_us))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
tunables->rate_limit_us = rate_limit_us;
|
|
|
|
|
|
|
|
list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook)
|
|
|
|
sg_policy->freq_update_delay_ns = rate_limit_us * NSEC_PER_USEC;
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct governor_attr rate_limit_us = __ATTR_RW(rate_limit_us);
|
|
|
|
|
2019-04-02 10:51:53 +08:00
|
|
|
static struct attribute *sugov_attrs[] = {
|
2016-04-02 07:09:12 +08:00
|
|
|
&rate_limit_us.attr,
|
|
|
|
NULL
|
|
|
|
};
|
2019-04-02 10:51:53 +08:00
|
|
|
ATTRIBUTE_GROUPS(sugov);
|
2016-04-02 07:09:12 +08:00
|
|
|
|
|
|
|
static struct kobj_type sugov_tunables_ktype = {
|
2019-04-02 10:51:53 +08:00
|
|
|
.default_groups = sugov_groups,
|
2016-04-02 07:09:12 +08:00
|
|
|
.sysfs_ops = &governor_sysfs_ops,
|
|
|
|
};
|
|
|
|
|
|
|
|
/********************** cpufreq governor interface *********************/
|
|
|
|
|
2018-12-03 17:56:21 +08:00
|
|
|
struct cpufreq_governor schedutil_gov;
|
2016-04-02 07:09:12 +08:00
|
|
|
|
|
|
|
static struct sugov_policy *sugov_policy_alloc(struct cpufreq_policy *policy)
|
|
|
|
{
|
|
|
|
struct sugov_policy *sg_policy;
|
|
|
|
|
|
|
|
sg_policy = kzalloc(sizeof(*sg_policy), GFP_KERNEL);
|
|
|
|
if (!sg_policy)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
sg_policy->policy = policy;
|
|
|
|
raw_spin_lock_init(&sg_policy->update_lock);
|
|
|
|
return sg_policy;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sugov_policy_free(struct sugov_policy *sg_policy)
|
|
|
|
{
|
|
|
|
kfree(sg_policy);
|
|
|
|
}
|
|
|
|
|
2016-11-15 16:23:22 +08:00
|
|
|
static int sugov_kthread_create(struct sugov_policy *sg_policy)
|
|
|
|
{
|
|
|
|
struct task_struct *thread;
|
2017-12-04 18:23:20 +08:00
|
|
|
struct sched_attr attr = {
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
.size = sizeof(struct sched_attr),
|
|
|
|
.sched_policy = SCHED_DEADLINE,
|
|
|
|
.sched_flags = SCHED_FLAG_SUGOV,
|
|
|
|
.sched_nice = 0,
|
|
|
|
.sched_priority = 0,
|
2017-12-04 18:23:20 +08:00
|
|
|
/*
|
|
|
|
* Fake (unused) bandwidth; workaround to "fix"
|
|
|
|
* priority inheritance.
|
|
|
|
*/
|
|
|
|
.sched_runtime = 1000000,
|
|
|
|
.sched_deadline = 10000000,
|
|
|
|
.sched_period = 10000000,
|
|
|
|
};
|
2016-11-15 16:23:22 +08:00
|
|
|
struct cpufreq_policy *policy = sg_policy->policy;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* kthread only required for slow path */
|
|
|
|
if (policy->fast_switch_enabled)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
kthread_init_work(&sg_policy->work, sugov_work);
|
|
|
|
kthread_init_worker(&sg_policy->worker);
|
|
|
|
thread = kthread_create(kthread_worker_fn, &sg_policy->worker,
|
|
|
|
"sugov:%d",
|
|
|
|
cpumask_first(policy->related_cpus));
|
|
|
|
if (IS_ERR(thread)) {
|
|
|
|
pr_err("failed to create sugov thread: %ld\n", PTR_ERR(thread));
|
|
|
|
return PTR_ERR(thread);
|
|
|
|
}
|
|
|
|
|
2017-12-04 18:23:20 +08:00
|
|
|
ret = sched_setattr_nocheck(thread, &attr);
|
2016-11-15 16:23:22 +08:00
|
|
|
if (ret) {
|
|
|
|
kthread_stop(thread);
|
2017-12-04 18:23:20 +08:00
|
|
|
pr_warn("%s: failed to set SCHED_DEADLINE\n", __func__);
|
2016-11-15 16:23:22 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
sg_policy->thread = thread;
|
Revert "cpufreq: schedutil: Don't restrict kthread to related_cpus unnecessarily"
This reverts commit e2cabe48c20efb174ce0c01190f8b9c5f3ea1d13.
Lifting the restriction that the sugov kthread is bound to the
policy->related_cpus for a system with a slow switching cpufreq driver,
which is able to perform DVFS from any cpu (e.g. cpufreq-dt), is not
only not beneficial it also harms Enery-Aware Scheduling (EAS) on
systems with asymmetric cpu capacities (e.g. Arm big.LITTLE).
The sugov kthread which does the update for the little cpus could
potentially run on a big cpu. It could prevent that the big cluster goes
into deeper idle states although all the tasks are running on the little
cluster.
Example: hikey960 w/ 4.16.0-rc6-+
Arm big.LITTLE with per-cluster DVFS
root@h960:~# cat /proc/cpuinfo | grep "^CPU part"
CPU part : 0xd03 (Cortex-A53, little cpu)
CPU part : 0xd03
CPU part : 0xd03
CPU part : 0xd03
CPU part : 0xd09 (Cortex-A73, big cpu)
CPU part : 0xd09
CPU part : 0xd09
CPU part : 0xd09
root@h960:/sys/devices/system/cpu/cpufreq# ls
policy0 policy4 schedutil
root@h960:/sys/devices/system/cpu/cpufreq# cat policy*/related_cpus
0 1 2 3
4 5 6 7
(1) w/o the revert:
root@h960:~# ps -eo pid,class,rtprio,pri,psr,comm | awk 'NR == 1 ||
/sugov/'
PID CLS RTPRIO PRI PSR COMMAND
1489 #6 0 140 1 sugov:0
1490 #6 0 140 0 sugov:4
The sugov kthread sugov:4 responsible for policy4 runs on cpu0. (In this
case both sugov kthreads run on little cpus).
cross policy (cluster) remote callback example:
...
migration/1-14 [001] enqueue_task_fair: this_cpu=1 cpu_of(rq)=5
migration/1-14 [001] sugov_update_shared: this_cpu=1 sg_cpu->cpu=5
sg_cpu->sg_policy->policy->related_cpus=4-7
sugov:4-1490 [000] sugov_work: this_cpu=0
sg_cpu->sg_policy->policy->related_cpus=4-7
...
The remote callback (this_cpu=1, target_cpu=5) is executed on cpu=0.
(2) w/ the revert:
root@h960:~# ps -eo pid,class,rtprio,pri,psr,comm | awk 'NR == 1 ||
/sugov/'
PID CLS RTPRIO PRI PSR COMMAND
1491 #6 0 140 2 sugov:0
1492 #6 0 140 4 sugov:4
The sugov kthread sugov:4 responsible for policy4 runs on cpu4.
cross policy (cluster) remote callback example:
...
migration/1-14 [001] enqueue_task_fair: this_cpu=1 cpu_of(rq)=7
migration/1-14 [001] sugov_update_shared: this_cpu=1 sg_cpu->cpu=7
sg_cpu->sg_policy->policy->related_cpus=4-7
sugov:4-1492 [004] sugov_work: this_cpu=4
sg_cpu->sg_policy->policy->related_cpus=4-7
...
The remote callback (this_cpu=1, target_cpu=7) is executed on cpu=4.
Now the sugov kthread executes again on the policy (cluster) for which
the Operating Performance Point (OPP) should be changed.
It avoids the problem that an otherwise idle policy (cluster) is running
schedutil (the sugov kthread) for another one.
Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2018-05-08 15:33:40 +08:00
|
|
|
kthread_bind_mask(thread, policy->related_cpus);
|
2016-11-15 16:23:23 +08:00
|
|
|
init_irq_work(&sg_policy->irq_work, sugov_irq_work);
|
|
|
|
mutex_init(&sg_policy->work_lock);
|
|
|
|
|
2016-11-15 16:23:22 +08:00
|
|
|
wake_up_process(thread);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sugov_kthread_stop(struct sugov_policy *sg_policy)
|
|
|
|
{
|
|
|
|
/* kthread only required for slow path */
|
|
|
|
if (sg_policy->policy->fast_switch_enabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
kthread_flush_worker(&sg_policy->worker);
|
|
|
|
kthread_stop(sg_policy->thread);
|
2016-11-15 16:23:23 +08:00
|
|
|
mutex_destroy(&sg_policy->work_lock);
|
2016-11-15 16:23:22 +08:00
|
|
|
}
|
|
|
|
|
2016-04-02 07:09:12 +08:00
|
|
|
static struct sugov_tunables *sugov_tunables_alloc(struct sugov_policy *sg_policy)
|
|
|
|
{
|
|
|
|
struct sugov_tunables *tunables;
|
|
|
|
|
|
|
|
tunables = kzalloc(sizeof(*tunables), GFP_KERNEL);
|
|
|
|
if (tunables) {
|
|
|
|
gov_attr_set_init(&tunables->attr_set, &sg_policy->tunables_hook);
|
|
|
|
if (!have_governor_per_policy())
|
|
|
|
global_tunables = tunables;
|
|
|
|
}
|
|
|
|
return tunables;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sugov_tunables_free(struct sugov_tunables *tunables)
|
|
|
|
{
|
|
|
|
if (!have_governor_per_policy())
|
|
|
|
global_tunables = NULL;
|
|
|
|
|
|
|
|
kfree(tunables);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sugov_init(struct cpufreq_policy *policy)
|
|
|
|
{
|
|
|
|
struct sugov_policy *sg_policy;
|
|
|
|
struct sugov_tunables *tunables;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
/* State should be equivalent to EXIT */
|
|
|
|
if (policy->governor_data)
|
|
|
|
return -EBUSY;
|
|
|
|
|
2016-11-15 16:23:21 +08:00
|
|
|
cpufreq_enable_fast_switch(policy);
|
|
|
|
|
2016-04-02 07:09:12 +08:00
|
|
|
sg_policy = sugov_policy_alloc(policy);
|
2016-11-15 16:23:21 +08:00
|
|
|
if (!sg_policy) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto disable_fast_switch;
|
|
|
|
}
|
2016-04-02 07:09:12 +08:00
|
|
|
|
2016-11-15 16:23:22 +08:00
|
|
|
ret = sugov_kthread_create(sg_policy);
|
|
|
|
if (ret)
|
|
|
|
goto free_sg_policy;
|
|
|
|
|
2016-04-02 07:09:12 +08:00
|
|
|
mutex_lock(&global_tunables_lock);
|
|
|
|
|
|
|
|
if (global_tunables) {
|
|
|
|
if (WARN_ON(have_governor_per_policy())) {
|
|
|
|
ret = -EINVAL;
|
2016-11-15 16:23:22 +08:00
|
|
|
goto stop_kthread;
|
2016-04-02 07:09:12 +08:00
|
|
|
}
|
|
|
|
policy->governor_data = sg_policy;
|
|
|
|
sg_policy->tunables = global_tunables;
|
|
|
|
|
|
|
|
gov_attr_set_get(&global_tunables->attr_set, &sg_policy->tunables_hook);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
tunables = sugov_tunables_alloc(sg_policy);
|
|
|
|
if (!tunables) {
|
|
|
|
ret = -ENOMEM;
|
2016-11-15 16:23:22 +08:00
|
|
|
goto stop_kthread;
|
2016-04-02 07:09:12 +08:00
|
|
|
}
|
|
|
|
|
2017-07-19 18:12:42 +08:00
|
|
|
tunables->rate_limit_us = cpufreq_policy_transition_delay_us(policy);
|
2016-04-02 07:09:12 +08:00
|
|
|
|
|
|
|
policy->governor_data = sg_policy;
|
|
|
|
sg_policy->tunables = tunables;
|
|
|
|
|
|
|
|
ret = kobject_init_and_add(&tunables->attr_set.kobj, &sugov_tunables_ktype,
|
|
|
|
get_governor_parent_kobj(policy), "%s",
|
|
|
|
schedutil_gov.name);
|
|
|
|
if (ret)
|
|
|
|
goto fail;
|
|
|
|
|
2016-11-15 16:23:20 +08:00
|
|
|
out:
|
2016-04-02 07:09:12 +08:00
|
|
|
mutex_unlock(&global_tunables_lock);
|
|
|
|
return 0;
|
|
|
|
|
2016-11-15 16:23:20 +08:00
|
|
|
fail:
|
2019-04-30 08:11:44 +08:00
|
|
|
kobject_put(&tunables->attr_set.kobj);
|
2016-04-02 07:09:12 +08:00
|
|
|
policy->governor_data = NULL;
|
|
|
|
sugov_tunables_free(tunables);
|
|
|
|
|
2016-11-15 16:23:22 +08:00
|
|
|
stop_kthread:
|
|
|
|
sugov_kthread_stop(sg_policy);
|
2016-04-02 07:09:12 +08:00
|
|
|
mutex_unlock(&global_tunables_lock);
|
|
|
|
|
2018-03-29 22:43:01 +08:00
|
|
|
free_sg_policy:
|
2016-04-02 07:09:12 +08:00
|
|
|
sugov_policy_free(sg_policy);
|
2016-11-15 16:23:21 +08:00
|
|
|
|
|
|
|
disable_fast_switch:
|
|
|
|
cpufreq_disable_fast_switch(policy);
|
|
|
|
|
2016-05-18 20:25:28 +08:00
|
|
|
pr_err("initialization failed (error %d)\n", ret);
|
2016-04-02 07:09:12 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-06-03 05:24:15 +08:00
|
|
|
static void sugov_exit(struct cpufreq_policy *policy)
|
2016-04-02 07:09:12 +08:00
|
|
|
{
|
|
|
|
struct sugov_policy *sg_policy = policy->governor_data;
|
|
|
|
struct sugov_tunables *tunables = sg_policy->tunables;
|
|
|
|
unsigned int count;
|
|
|
|
|
|
|
|
mutex_lock(&global_tunables_lock);
|
|
|
|
|
|
|
|
count = gov_attr_set_put(&tunables->attr_set, &sg_policy->tunables_hook);
|
|
|
|
policy->governor_data = NULL;
|
|
|
|
if (!count)
|
|
|
|
sugov_tunables_free(tunables);
|
|
|
|
|
|
|
|
mutex_unlock(&global_tunables_lock);
|
|
|
|
|
2016-11-15 16:23:22 +08:00
|
|
|
sugov_kthread_stop(sg_policy);
|
2016-04-02 07:09:12 +08:00
|
|
|
sugov_policy_free(sg_policy);
|
2016-11-15 16:23:21 +08:00
|
|
|
cpufreq_disable_fast_switch(policy);
|
2016-04-02 07:09:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int sugov_start(struct cpufreq_policy *policy)
|
|
|
|
{
|
|
|
|
struct sugov_policy *sg_policy = policy->governor_data;
|
|
|
|
unsigned int cpu;
|
|
|
|
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
sg_policy->freq_update_delay_ns = sg_policy->tunables->rate_limit_us * NSEC_PER_USEC;
|
|
|
|
sg_policy->last_freq_update_time = 0;
|
2018-05-09 18:35:24 +08:00
|
|
|
sg_policy->next_freq = 0;
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
sg_policy->work_in_progress = false;
|
2019-08-07 15:06:01 +08:00
|
|
|
sg_policy->limits_changed = false;
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
sg_policy->cached_raw_freq = 0;
|
2016-04-02 07:09:12 +08:00
|
|
|
|
cpufreq: schedutil: Don't skip freq update if need_freq_update is set
The cpufreq policy's frequency limits (min/max) can get changed at any
point of time, while schedutil is trying to update the next frequency.
Though the schedutil governor has necessary locking and support in place
to make sure we don't miss any of those updates, there is a corner case
where the governor will find that the CPU is already running at the
desired frequency and so may skip an update.
For example, consider that the CPU can run at 1 GHz, 1.2 GHz and 1.4 GHz
and is running at 1 GHz currently. Schedutil tries to update the
frequency to 1.2 GHz, during this time the policy limits get changed as
policy->min = 1.4 GHz. As schedutil (and cpufreq core) does clamp the
frequency at various instances, we will eventually set the frequency to
1.4 GHz, while we will save 1.2 GHz in sg_policy->next_freq.
Now lets say the policy limits get changed back at this time with
policy->min as 1 GHz. The next time schedutil is invoked by the
scheduler, we will reevaluate the next frequency (because
need_freq_update will get set due to limits change event) and lets say
we want to set the frequency to 1.2 GHz again. At this point
sugov_update_next_freq() will find the next_freq == current_freq and
will abort the update, while the CPU actually runs at 1.4 GHz.
Until now need_freq_update was used as a flag to indicate that the
policy's frequency limits have changed, and that we should consider the
new limits while reevaluating the next frequency.
This patch fixes the above mentioned issue by extending the purpose of
the need_freq_update flag. If this flag is set now, the schedutil
governor will not try to abort a frequency change even if next_freq ==
current_freq.
As similar behavior is required in the case of
CPUFREQ_NEED_UPDATE_LIMITS flag as well, need_freq_update will never be
set to false if that flag is set for the driver.
We also don't need to consider the need_freq_update flag in
sugov_update_single() anymore to handle the special case of busy CPU, as
we won't abort a frequency update anymore.
Reported-by: zhuguangqing <zhuguangqing@xiaomi.com>
Suggested-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
[ rjw: Rearrange code to avoid a branch ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2020-10-30 15:21:08 +08:00
|
|
|
sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS);
|
|
|
|
|
2016-04-02 07:09:12 +08:00
|
|
|
for_each_cpu(cpu, policy->cpus) {
|
|
|
|
struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu);
|
|
|
|
|
2017-03-19 21:30:02 +08:00
|
|
|
memset(sg_cpu, 0, sizeof(*sg_cpu));
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
sg_cpu->cpu = cpu;
|
|
|
|
sg_cpu->sg_policy = sg_policy;
|
2017-07-07 01:53:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for_each_cpu(cpu, policy->cpus) {
|
|
|
|
struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu);
|
|
|
|
|
2017-03-19 21:30:02 +08:00
|
|
|
cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
|
|
|
|
policy_is_shared(policy) ?
|
|
|
|
sugov_update_shared :
|
|
|
|
sugov_update_single);
|
2016-04-02 07:09:12 +08:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-06-03 05:24:15 +08:00
|
|
|
static void sugov_stop(struct cpufreq_policy *policy)
|
2016-04-02 07:09:12 +08:00
|
|
|
{
|
|
|
|
struct sugov_policy *sg_policy = policy->governor_data;
|
|
|
|
unsigned int cpu;
|
|
|
|
|
|
|
|
for_each_cpu(cpu, policy->cpus)
|
|
|
|
cpufreq_remove_update_util_hook(cpu);
|
|
|
|
|
2018-11-07 11:13:54 +08:00
|
|
|
synchronize_rcu();
|
2016-04-02 07:09:12 +08:00
|
|
|
|
2016-11-15 16:23:23 +08:00
|
|
|
if (!policy->fast_switch_enabled) {
|
|
|
|
irq_work_sync(&sg_policy->irq_work);
|
|
|
|
kthread_cancel_work_sync(&sg_policy->work);
|
|
|
|
}
|
2016-04-02 07:09:12 +08:00
|
|
|
}
|
|
|
|
|
2016-06-03 05:24:15 +08:00
|
|
|
static void sugov_limits(struct cpufreq_policy *policy)
|
2016-04-02 07:09:12 +08:00
|
|
|
{
|
|
|
|
struct sugov_policy *sg_policy = policy->governor_data;
|
|
|
|
|
|
|
|
if (!policy->fast_switch_enabled) {
|
|
|
|
mutex_lock(&sg_policy->work_lock);
|
2016-05-18 20:25:31 +08:00
|
|
|
cpufreq_policy_apply_limits(policy);
|
2016-04-02 07:09:12 +08:00
|
|
|
mutex_unlock(&sg_policy->work_lock);
|
|
|
|
}
|
|
|
|
|
2019-08-07 15:06:01 +08:00
|
|
|
sg_policy->limits_changed = true;
|
2016-04-02 07:09:12 +08:00
|
|
|
}
|
|
|
|
|
2018-12-03 17:56:21 +08:00
|
|
|
struct cpufreq_governor schedutil_gov = {
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
.name = "schedutil",
|
|
|
|
.owner = THIS_MODULE,
|
2020-11-11 01:25:57 +08:00
|
|
|
.flags = CPUFREQ_GOV_DYNAMIC_SWITCHING,
|
sched: Clean up and harmonize the coding style of the scheduler code base
A good number of small style inconsistencies have accumulated
in the scheduler core, so do a pass over them to harmonize
all these details:
- fix speling in comments,
- use curly braces for multi-line statements,
- remove unnecessary parentheses from integer literals,
- capitalize consistently,
- remove stray newlines,
- add comments where necessary,
- remove invalid/unnecessary comments,
- align structure definitions and other data types vertically,
- add missing newlines for increased readability,
- fix vertical tabulation where it's misaligned,
- harmonize preprocessor conditional block labeling
and vertical alignment,
- remove line-breaks where they uglify the code,
- add newline after local variable definitions,
No change in functionality:
md5:
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.before.asm
1191fa0a890cfa8132156d2959d7e9e2 built-in.o.after.asm
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2018-03-03 21:01:12 +08:00
|
|
|
.init = sugov_init,
|
|
|
|
.exit = sugov_exit,
|
|
|
|
.start = sugov_start,
|
|
|
|
.stop = sugov_stop,
|
|
|
|
.limits = sugov_limits,
|
2016-04-02 07:09:12 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL
|
|
|
|
struct cpufreq_governor *cpufreq_default_governor(void)
|
|
|
|
{
|
|
|
|
return &schedutil_gov;
|
|
|
|
}
|
|
|
|
#endif
|
2016-08-17 04:14:55 +08:00
|
|
|
|
2020-06-29 16:24:59 +08:00
|
|
|
cpufreq_governor_init(schedutil_gov);
|
2018-12-03 17:56:21 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_ENERGY_MODEL
|
|
|
|
extern bool sched_energy_update;
|
|
|
|
extern struct mutex sched_energy_mutex;
|
|
|
|
|
|
|
|
static void rebuild_sd_workfn(struct work_struct *work)
|
|
|
|
{
|
|
|
|
mutex_lock(&sched_energy_mutex);
|
|
|
|
sched_energy_update = true;
|
|
|
|
rebuild_sched_domains();
|
|
|
|
sched_energy_update = false;
|
|
|
|
mutex_unlock(&sched_energy_mutex);
|
|
|
|
}
|
|
|
|
static DECLARE_WORK(rebuild_sd_work, rebuild_sd_workfn);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* EAS shouldn't be attempted without sugov, so rebuild the sched_domains
|
|
|
|
* on governor changes to make sure the scheduler knows about it.
|
|
|
|
*/
|
|
|
|
void sched_cpufreq_governor_change(struct cpufreq_policy *policy,
|
|
|
|
struct cpufreq_governor *old_gov)
|
|
|
|
{
|
|
|
|
if (old_gov == &schedutil_gov || policy->governor == &schedutil_gov) {
|
|
|
|
/*
|
|
|
|
* When called from the cpufreq_register_driver() path, the
|
|
|
|
* cpu_hotplug_lock is already held, so use a work item to
|
|
|
|
* avoid nested locking in rebuild_sched_domains().
|
|
|
|
*/
|
|
|
|
schedule_work(&rebuild_sd_work);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|