From: "Bálint Czobor" <czoborbalint@gmail.com>
To: "Rafael J. Wysocki" <rjw@rjwysocki.net>,
Viresh Kumar <viresh.kumar@linaro.org>
Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org,
"Todd Poynor" <toddpoynor@google.com>,
"Bálint Czobor" <czoborbalint@gmail.com>
Subject: [PATCH 31/70] cpufreq: interactive: adjust load for changes in speed
Date: Tue, 27 Oct 2015 18:30:19 +0100 [thread overview]
Message-ID: <1445967059-6897-31-git-send-email-czoborbalint@gmail.com> (raw)
In-Reply-To: <1445967059-6897-1-git-send-email-czoborbalint@gmail.com>
From: Todd Poynor <toddpoynor@google.com>
Add notifier for speed transitions. Keep a count of CPU active
microseconds times current frequency, converted to a percentage relative
to the current frequency when load is evaluated.
Change-Id: I5c27adb11081c50490219784ca57cc46e97fc28c
Signed-off-by: Todd Poynor <toddpoynor@google.com>
Signed-off-by: Bálint Czobor <czoborbalint@gmail.com>
---
drivers/cpufreq/cpufreq_interactive.c | 87 +++++++++++++++++++++++++++------
1 file changed, 71 insertions(+), 16 deletions(-)
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 3d8e7b4..d0d51ee 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -41,8 +41,11 @@ static atomic_t active_count = ATOMIC_INIT(0);
struct cpufreq_interactive_cpuinfo {
struct timer_list cpu_timer;
int timer_idlecancel;
+ spinlock_t load_lock; /* protects the next 4 fields */
u64 time_in_idle;
u64 time_in_idle_timestamp;
+ u64 cputime_speedadj;
+ u64 cputime_speedadj_timestamp;
struct cpufreq_policy *policy;
struct cpufreq_frequency_table *freq_table;
unsigned int target_freq;
@@ -121,9 +124,13 @@ static void cpufreq_interactive_timer_resched(
{
mod_timer_pinned(&pcpu->cpu_timer,
jiffies + usecs_to_jiffies(timer_rate));
+ spin_lock(&pcpu->load_lock);
pcpu->time_in_idle =
get_cpu_idle_time_us(smp_processor_id(),
&pcpu->time_in_idle_timestamp);
+ pcpu->cputime_speedadj = 0;
+ pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp;
+ spin_unlock(&pcpu->load_lock);
}
static unsigned int freq_to_targetload(unsigned int freq)
@@ -148,10 +155,9 @@ static unsigned int freq_to_targetload(unsigned int freq)
*/
static unsigned int choose_freq(
- struct cpufreq_interactive_cpuinfo *pcpu, unsigned int curload)
+ struct cpufreq_interactive_cpuinfo *pcpu, unsigned int loadadjfreq)
{
unsigned int freq = pcpu->policy->cur;
- unsigned int loadadjfreq = freq * curload;
unsigned int prevfreq, freqmin, freqmax;
unsigned int tl;
int index;
@@ -230,16 +236,36 @@ static unsigned int choose_freq(
return freq;
}
-static void cpufreq_interactive_timer(unsigned long data)
+static u64 update_load(int cpu)
{
+ struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu);
u64 now;
+ u64 now_idle;
unsigned int delta_idle;
unsigned int delta_time;
+ u64 active_time;
+
+ now_idle = get_cpu_idle_time_us(cpu, &now);
+ delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle);
+ delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp);
+ active_time = delta_time - delta_idle;
+ pcpu->cputime_speedadj += active_time * pcpu->policy->cur;
+
+ pcpu->time_in_idle = now_idle;
+ pcpu->time_in_idle_timestamp = now;
+ return now;
+}
+
+static void cpufreq_interactive_timer(unsigned long data)
+{
+ u64 now;
+ unsigned int delta_time;
+ u64 cputime_speedadj;
int cpu_load;
struct cpufreq_interactive_cpuinfo *pcpu =
&per_cpu(cpuinfo, data);
- u64 now_idle;
unsigned int new_freq;
+ unsigned int loadadjfreq;
unsigned int index;
unsigned long flags;
@@ -248,26 +274,24 @@ static void cpufreq_interactive_timer(unsigned long data)
if (!pcpu->governor_enabled)
goto exit;
- now_idle = get_cpu_idle_time_us(data, &now);
- delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle);
- delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp);
+ spin_lock(&pcpu->load_lock);
+ now = update_load(data);
+ delta_time = (unsigned int)(now - pcpu->cputime_speedadj_timestamp);
+ cputime_speedadj = pcpu->cputime_speedadj;
+ spin_unlock(&pcpu->load_lock);
- /*
- * If timer ran less than 1ms after short-term sample started, retry.
- */
- if (delta_time < 1000)
+ if (WARN_ON_ONCE(!delta_time))
goto rearm;
- if (delta_idle > delta_time)
- cpu_load = 0;
- else
- cpu_load = 100 * (delta_time - delta_idle) / delta_time;
+ do_div(cputime_speedadj, delta_time);
+ loadadjfreq = (unsigned int)cputime_speedadj * 100;
+ cpu_load = loadadjfreq / pcpu->target_freq;
if ((cpu_load >= go_hispeed_load || boost_val) &&
pcpu->target_freq < hispeed_freq)
new_freq = hispeed_freq;
else
- new_freq = choose_freq(pcpu, cpu_load);
+ new_freq = choose_freq(pcpu, loadadjfreq);
if (pcpu->target_freq >= hispeed_freq &&
new_freq > pcpu->target_freq &&
@@ -498,6 +522,32 @@ static void cpufreq_interactive_boost(void)
wake_up_process(speedchange_task);
}
+static int cpufreq_interactive_notifier(
+ struct notifier_block *nb, unsigned long val, void *data)
+{
+ struct cpufreq_freqs *freq = data;
+ struct cpufreq_interactive_cpuinfo *pcpu;
+ int cpu;
+
+ if (val == CPUFREQ_POSTCHANGE) {
+ pcpu = &per_cpu(cpuinfo, freq->cpu);
+
+ for_each_cpu(cpu, pcpu->policy->cpus) {
+ struct cpufreq_interactive_cpuinfo *pjcpu =
+ &per_cpu(cpuinfo, cpu);
+ spin_lock(&pjcpu->load_lock);
+ update_load(cpu);
+ spin_unlock(&pjcpu->load_lock);
+ }
+ }
+
+ return 0;
+}
+
+static struct notifier_block cpufreq_notifier_block = {
+ .notifier_call = cpufreq_interactive_notifier,
+};
+
static ssize_t show_target_loads(
struct kobject *kobj, struct attribute *attr, char *buf)
{
@@ -817,6 +867,8 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
return rc;
idle_notifier_register(&cpufreq_interactive_idle_nb);
+ cpufreq_register_notifier(
+ &cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
break;
case CPUFREQ_GOV_STOP:
@@ -830,6 +882,8 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
if (atomic_dec_return(&active_count) > 0)
return 0;
+ cpufreq_unregister_notifier(
+ &cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
idle_notifier_unregister(&cpufreq_interactive_idle_nb);
sysfs_remove_group(cpufreq_global_kobject,
&interactive_attr_group);
@@ -868,6 +922,7 @@ static int __init cpufreq_interactive_init(void)
init_timer_deferrable(&pcpu->cpu_timer);
pcpu->cpu_timer.function = cpufreq_interactive_timer;
pcpu->cpu_timer.data = i;
+ spin_lock_init(&pcpu->load_lock);
}
spin_lock_init(&target_loads_lock);
--
1.7.9.5
next prev parent reply other threads:[~2015-10-27 17:54 UTC|newest]
Thread overview: 78+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-10-27 17:29 [PATCH 01/70] cpufreq: interactive: New 'interactive' governor Bálint Czobor
2015-10-27 17:29 ` [PATCH 02/70] cpufreq interactive governor: event tracing Bálint Czobor
2015-10-27 17:29 ` [PATCH 03/70] cpufreq: interactive: apply intermediate load to max speed not current Bálint Czobor
2015-10-27 17:29 ` [PATCH 04/70] cpufreq: interactive: set at least hispeed when above hispeed load Bálint Czobor
2015-10-27 17:29 ` [PATCH 05/70] cpufreq: interactive: don't drop speed if recently at higher load Bálint Czobor
2015-10-27 17:29 ` [PATCH 06/70] cpufreq: interactive: configurable delay before raising above hispeed Bálint Czobor
2015-10-27 17:29 ` [PATCH 07/70] cpufreq: interactive: adjust code and documentation to match Bálint Czobor
2015-10-27 17:29 ` [PATCH 08/70] cpufreq: interactive: base hispeed bump on target freq, not actual Bálint Czobor
2015-10-27 17:29 ` [PATCH 09/70] cpufreq: interactive: Separate speed target revalidate time and initial set time Bálint Czobor
2015-10-27 17:29 ` [PATCH 10/70] cpufreq: interactive: Boost frequency on touchscreen input Bálint Czobor
2015-10-27 17:29 ` [PATCH 11/70] cpufreq: interactive: remove unused target_validate_time_in_idle Bálint Czobor
2015-10-27 17:30 ` [PATCH 12/70] cpufreq: interactive: Add sysfs boost interface for hints from userspace Bálint Czobor
2015-10-27 17:30 ` [PATCH 13/70] cpufreq: interactive: set floor for boosted speed Bálint Czobor
2015-10-27 17:30 ` [PATCH 14/70] cpufreq: interactive: add boost pulse interface Bálint Czobor
2015-10-27 17:30 ` [PATCH 15/70] cpufreq-interactive: Compile fixup Bálint Czobor
2015-10-27 17:30 ` [PATCH 16/70] cpufreq: interactive: restart above_hispeed_delay at each hispeed load Bálint Czobor
2015-10-27 17:30 ` [PATCH 17/70] cpufreq: interactive: take idle notifications only when active Bálint Czobor
2015-10-27 20:56 ` kbuild test robot
2015-10-27 17:30 ` [PATCH 18/70] cpufreq: interactive: keep freezer happy when not current governor Bálint Czobor
2015-10-27 17:30 ` [PATCH 19/70] cpufreq: interactive: handle speed up and down in the realtime task Bálint Czobor
2015-10-27 17:30 ` [PATCH 20/70] cpufreq: interactive: remove input_boost handling Bálint Czobor
2015-10-27 17:30 ` [PATCH 21/70] cpufreq: interactive: always limit initial speed bump to hispeed Bálint Czobor
2015-10-27 17:30 ` [PATCH 22/70] cpufreq: interactive: run at fraction of hispeed_freq when load is low Bálint Czobor
2015-10-27 17:30 ` [PATCH 23/70] cpufreq: interactive: pin timers to associated CPU Bálint Czobor
2015-10-27 17:30 ` [PATCH 24/70] cpufreq: interactive: use deferrable timer by default Bálint Czobor
2015-10-27 17:30 ` [PATCH 25/70] cpufreq: interactive: kick timer on idle exit past expiry Bálint Czobor
2015-10-27 17:30 ` [PATCH 26/70] cpufreq: interactive: trace actual speed in target speed decisions Bálint Czobor
2015-10-27 17:30 ` [PATCH 27/70] cpufreq: interactive: change speed according to current speed and target load Bálint Czobor
2015-10-27 17:30 ` [PATCH 28/70] cpufreq: interactive: apply above_hispeed_delay to each step above hispeed Bálint Czobor
2015-10-27 17:30 ` [PATCH 29/70] cpufreq: interactive: allow arbitrary speed / target load mappings Bálint Czobor
2015-10-27 17:30 ` [PATCH 30/70] cpufreq: interactive: remove load since last speed change Bálint Czobor
2015-10-27 17:30 ` Bálint Czobor [this message]
2015-10-27 17:30 ` [PATCH 32/70] cpufreq: interactive: specify duration of CPU speed boost pulse Bálint Czobor
2015-10-27 17:30 ` [PATCH 33/70] cpufreq: interactive: add timer slack to limit idle at speed > min Bálint Czobor
2015-10-27 17:30 ` [PATCH 34/70] cpufreq: interactive: fix boosting logic Bálint Czobor
2015-10-27 17:30 ` [PATCH 35/70] cpufreq: interactive: fix racy timer stopping Bálint Czobor
2015-10-27 17:30 ` [PATCH 36/70] cpufreq: interactive: fix race on timer restart on governor start Bálint Czobor
2015-10-27 17:30 ` [PATCH 37/70] cpufreq: interactive: default go_hispeed_load 99%, doc updates Bálint Czobor
2015-10-27 17:30 ` [PATCH 38/70] cpufreq: interactive: init default values at compile time Bálint Czobor
2015-10-27 17:30 ` [PATCH 39/70] cpufreq: interactive: don't handle transition notification if not enabled Bálint Czobor
2015-10-27 17:30 ` [PATCH 40/70] cpufreq: interactive: fix deadlock on spinlock in timer Bálint Czobor
2015-10-27 17:30 ` [PATCH 41/70] cpufreq: interactive: fix race on governor start/stop Bálint Czobor
2015-10-27 17:30 ` [PATCH 42/70] cpufreq: interactive: allow arbitrary speed / delay mappings Bálint Czobor
2015-10-27 17:30 ` [PATCH 43/70] cpufreq: interactive: add io_is_busy interface Bálint Czobor
2015-10-27 17:30 ` [PATCH 44/70] cpufreq: interactive: fix crash on error paths in get_tokenized_data Bálint Czobor
2015-10-27 17:30 ` [PATCH 45/70] cpufreq: interactive: base above_hispeed_delay on target freq, not current Bálint Czobor
2015-10-27 17:30 ` [PATCH 46/70] cpufreq: interactive: fix uninitialized spinlock Bálint Czobor
2015-10-27 17:30 ` [PATCH 47/70] cpufreq: interactive: handle errors from cpufreq_frequency_table_target Bálint Czobor
2015-10-27 17:30 ` [PATCH 48/70] cpufreq: interactive: reduce chance of zero time delta on load eval Bálint Czobor
2015-10-27 17:30 ` [PATCH 49/70] cpufreq: interactive: avoid underflow on active time calculation Bálint Czobor
2015-10-27 17:30 ` [PATCH 50/70] cpufreq: interactive: fix race on cpufreq TRANSITION notifier Bálint Czobor
2015-10-27 17:30 ` [PATCH 51/70] cpufreq: interactive: resched timer if max freq raised Bálint Czobor
2015-10-27 17:30 ` [PATCH 52/70] cpufreq: interactive: fix show_target_loads and show_above_hispeed_delay Bálint Czobor
2015-10-27 17:30 ` [PATCH 53/70] cpufreq: interactive: Remove unnecessary cpu_online() check Bálint Czobor
2015-10-27 17:30 ` [PATCH 54/70] cpufreq: interactive: Move definition of cpufreq_gov_interactive downwards Bálint Czobor
2015-10-27 17:30 ` [PATCH 55/70] cpufreq: Interactive: Implement per policy instances of governor Bálint Czobor
2015-10-27 17:30 ` [PATCH 56/70] cpufreq: interactive: delete timers for GOV_START Bálint Czobor
2015-10-27 17:30 ` [PATCH 57/70] cpufreq: interactive: fix compiling warnings Bálint Czobor
2015-10-27 17:30 ` [PATCH 58/70] cpufreq: interactive: fix NULL pointer dereference at sysfs ops Bálint Czobor
2015-10-27 17:30 ` [PATCH 59/70] cpufreq: interactive: Use generic get_cpu_idle_time() from cpufreq.c Bálint Czobor
2015-10-27 17:30 ` [PATCH 60/70] cpufreq: interactive: hold reference on global cpufreq kobject if needed Bálint Czobor
2015-10-27 17:30 ` [PATCH 61/70] cpufreq: interactive: restructure CPUFREQ_GOV_LIMITS Bálint Czobor
2015-10-27 17:30 ` [PATCH 62/70] cpufreq: interactive: turn boost_pulse off on boost off Bálint Czobor
2015-10-27 17:30 ` [PATCH 63/70] cpufreq: interactive: remove compilation error from commit 49cc72365fb7ee87762a7ccc6a32ef68627216c5 Bálint Czobor
2015-10-27 17:30 ` [PATCH 64/70] cpufreq: interactive: prevents the frequency to directly raise above the hispeed_freq from a lower frequency Bálint Czobor
2015-10-27 17:30 ` [PATCH 65/70] cpufreq: interactive: make common_tunables static Bálint Czobor
2015-10-27 17:30 ` [PATCH 66/70] cpufreq: interactive: Fix compile errors in accordance with changes from 3.14 to 3.18 Bálint Czobor
2015-10-28 2:15 ` kbuild test robot
2015-10-27 17:30 ` [PATCH 67/70] cpufreq: interactive: Put global cpufreq kobject on failure Bálint Czobor
2015-10-27 17:30 ` [PATCH 68/70] subsystem: CPU FREQUENCY DRIVERS- Set cpu_load calculation on current frequency Bálint Czobor
2015-10-27 17:30 ` [PATCH 69/70] cpufreq: interactive: Don't set floor_validate_time during boost Bálint Czobor
2015-10-27 17:30 ` [PATCH 70/70] cpufreq: interactive: Round up timer_rate to match jiffy Bálint Czobor
2015-10-27 20:44 ` [PATCH 01/70] cpufreq: interactive: New 'interactive' governor kbuild test robot
2015-10-28 0:59 ` Rafael J. Wysocki
2015-10-28 3:00 ` Viresh Kumar
[not found] ` <CAL6DFdfsDTtkkpLJ7kg9L9rFh+Ho6DC7x9a+F3x9DydvXHfbPQ@mail.gmail.com>
[not found] ` <CAL6DFdeSbzM5go==i8Z_CJ19VrAMWVVWF5NuD+VNMONaPK5zLA@mail.gmail.com>
2015-10-29 1:42 ` Viresh Kumar
2015-11-02 14:02 ` Peter Zijlstra
2015-11-02 18:06 ` Steve Muckle
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1445967059-6897-31-git-send-email-czoborbalint@gmail.com \
--to=czoborbalint@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=rjw@rjwysocki.net \
--cc=toddpoynor@google.com \
--cc=viresh.kumar@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®