aboutsummaryrefslogtreecommitdiff
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorTodd Poynor <toddpoynor@google.com>2012-10-08 20:14:34 -0700
committerArve Hjønnevåg <arve@android.com>2013-07-01 14:16:13 -0700
commit9c6633a1bf94238855eb250f99850842dd9b701f (patch)
tree7acfd8a588de271b8fd597adecb5fc34946ccc3f /drivers/cpufreq
parenta407739135ec10bee00bcba4523f244827e6421e (diff)
cpufreq: interactive: kick timer on idle exit past expiry
The deferrable timer list isn't checked on all idle exits, such as when hi-res timers expire or ISRs schedule workers. If the idle loop is exited and it's past time to run the governor load polling timer, run it immediately. This ensures we handle load spikes caused by actvity that does not run the normal timer list. Rename the field that timestamps the "time_in_idle" value to be more accurate. Change-Id: Ied590ecbefc83c9a9ec5eb9e31903557f6fa1614 Signed-off-by: Todd Poynor <toddpoynor@google.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c43
1 files changed, 20 insertions, 23 deletions
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 71887cabfad..81537692903 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -42,7 +42,7 @@ struct cpufreq_interactive_cpuinfo {
struct timer_list cpu_timer;
int timer_idlecancel;
u64 time_in_idle;
- u64 idle_exit_time;
+ u64 time_in_idle_timestamp;
u64 target_set_time;
u64 target_set_time_in_idle;
struct cpufreq_policy *policy;
@@ -111,6 +111,16 @@ struct cpufreq_governor cpufreq_gov_interactive = {
.owner = THIS_MODULE,
};
+static void cpufreq_interactive_timer_resched(
+ struct cpufreq_interactive_cpuinfo *pcpu)
+{
+ mod_timer_pinned(&pcpu->cpu_timer,
+ jiffies + usecs_to_jiffies(timer_rate));
+ pcpu->time_in_idle =
+ get_cpu_idle_time_us(smp_processor_id(),
+ &pcpu->time_in_idle_timestamp);
+}
+
static void cpufreq_interactive_timer(unsigned long data)
{
u64 now;
@@ -118,8 +128,6 @@ static void cpufreq_interactive_timer(unsigned long data)
unsigned int delta_time;
int cpu_load;
int load_since_change;
- u64 time_in_idle;
- u64 idle_exit_time;
struct cpufreq_interactive_cpuinfo *pcpu =
&per_cpu(cpuinfo, data);
u64 now_idle;
@@ -132,11 +140,9 @@ static void cpufreq_interactive_timer(unsigned long data)
if (!pcpu->governor_enabled)
goto exit;
- time_in_idle = pcpu->time_in_idle;
- idle_exit_time = pcpu->idle_exit_time;
now_idle = get_cpu_idle_time_us(data, &now);
- delta_idle = (unsigned int)(now_idle - time_in_idle);
- delta_time = (unsigned int)(now - idle_exit_time);
+ delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle);
+ delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp);
/*
* If timer ran less than 1ms after short-term sample started, retry.
@@ -253,10 +259,7 @@ rearm:
if (governidle && pcpu->target_freq == pcpu->policy->min)
pcpu->timer_idlecancel = 1;
- pcpu->time_in_idle = get_cpu_idle_time_us(
- data, &pcpu->idle_exit_time);
- mod_timer_pinned(&pcpu->cpu_timer,
- jiffies + usecs_to_jiffies(timer_rate));
+ cpufreq_interactive_timer_resched(pcpu);
}
exit:
@@ -284,12 +287,8 @@ static void cpufreq_interactive_idle_start(void)
* the CPUFreq driver.
*/
if (!pending) {
- pcpu->time_in_idle = get_cpu_idle_time_us(
- smp_processor_id(), &pcpu->idle_exit_time);
pcpu->timer_idlecancel = 0;
- mod_timer_pinned(
- &pcpu->cpu_timer,
- jiffies + usecs_to_jiffies(timer_rate));
+ cpufreq_interactive_timer_resched(pcpu);
}
} else if (governidle) {
/*
@@ -316,15 +315,13 @@ static void cpufreq_interactive_idle_end(void)
/* Arm the timer for 1-2 ticks later if not already. */
if (!timer_pending(&pcpu->cpu_timer)) {
- pcpu->time_in_idle =
- get_cpu_idle_time_us(smp_processor_id(),
- &pcpu->idle_exit_time);
pcpu->timer_idlecancel = 0;
- mod_timer_pinned(
- &pcpu->cpu_timer,
- jiffies + usecs_to_jiffies(timer_rate));
+ cpufreq_interactive_timer_resched(pcpu);
+ } else if (!governidle &&
+ time_after_eq(jiffies, pcpu->cpu_timer.expires)) {
+ del_timer(&pcpu->cpu_timer);
+ cpufreq_interactive_timer(smp_processor_id());
}
-
}
static int cpufreq_interactive_speedchange_task(void *data)