aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRohit Gupta <rohgup@codeaurora.org>2015-03-06 18:46:04 -0800
committerSteve Kondik <shade@chemlab.org>2015-05-03 08:41:25 +0000
commit493c3a1b582ff4c9987d179c6e3a710269c74177 (patch)
tree836d6718cbd5649ae673eebcebc3d592a72f7bc4
parentb092e186be01f2ee450be28797cc1cc6e1f006d8 (diff)
cpufreq: interactive: Rearm governor timer at max freq
Currently interactive governor timer doesn't re-arm itself when it selects policy->max as the new frequency to go to. On hitting idle for the first time at max frequency timer is armed again. This mechanism doesn't have any noticeable performance benefits since CPUs running at max frequencies without going into idles show high loads which prevents the governor from lowering their frequencies. This change rearms the timer even at max frequency which removes the need to handle idle starts. This simplifies the code and also makes the governor timer windows more regular so that the notifications going out from the governor are uniformly spaced apart. Max freq hysteresis start timestamp is refreshed everytime policy->max is selected as the new frequency to prevent stepping down from max frequency earlier than intended. Change-Id: I9c137113b703f2064f1e668628db91de94cc0887 Signed-off-by: Rohit Gupta <rohgup@codeaurora.org>
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c80
1 files changed, 8 insertions, 72 deletions
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index fd47747a7e8..7393f2a013c 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -55,7 +55,7 @@ struct cpufreq_interactive_cpuinfo {
u64 floor_validate_time;
u64 hispeed_validate_time; /* cluster hispeed_validate_time */
u64 local_hvtime; /* per-cpu hispeed_validate_time */
- u64 max_freq_idle_start_time;
+ u64 max_freq_hyst_start_time;
struct rw_semaphore enable_sem;
int governor_enabled;
};
@@ -419,9 +419,8 @@ static void cpufreq_interactive_timer(unsigned long data)
new_freq = pcpu->freq_table[index].frequency;
- if (pcpu->target_freq >= pcpu->policy->max
- && new_freq < pcpu->target_freq
- && now - pcpu->max_freq_idle_start_time < max_freq_hysteresis) {
+ if (new_freq < pcpu->target_freq &&
+ now - pcpu->max_freq_hyst_start_time < max_freq_hysteresis) {
trace_cpufreq_interactive_notyet(data, cpu_load,
pcpu->target_freq, pcpu->policy->cur, new_freq);
spin_unlock_irqrestore(&pcpu->target_freq_lock, flags);
@@ -455,12 +454,15 @@ static void cpufreq_interactive_timer(unsigned long data)
pcpu->floor_validate_time = now;
}
+ if (new_freq == pcpu->policy->max)
+ pcpu->max_freq_hyst_start_time = now;
+
if (pcpu->target_freq == new_freq) {
trace_cpufreq_interactive_already(
data, cpu_load, pcpu->target_freq,
pcpu->policy->cur, new_freq);
spin_unlock_irqrestore(&pcpu->target_freq_lock, flags);
- goto rearm_if_notmax;
+ goto rearm;
}
trace_cpufreq_interactive_target(data, cpu_load, pcpu->target_freq,
@@ -473,14 +475,6 @@ static void cpufreq_interactive_timer(unsigned long data)
spin_unlock_irqrestore(&speedchange_cpumask_lock, flags);
wake_up_process(speedchange_task);
-rearm_if_notmax:
- /*
- * Already set max speed and don't see a need to change that,
- * wait until next idle to re-evaluate, don't need timer.
- */
- if (pcpu->target_freq == pcpu->policy->max)
- goto exit;
-
rearm:
if (!timer_pending(&pcpu->cpu_timer))
cpufreq_interactive_timer_resched(data);
@@ -490,58 +484,6 @@ exit:
return;
}
-static void cpufreq_interactive_idle_start(void)
-{
- struct cpufreq_interactive_cpuinfo *pcpu =
- &per_cpu(cpuinfo, smp_processor_id());
- int pending;
- unsigned long flags;
- u64 now;
-
- if (!down_read_trylock(&pcpu->enable_sem))
- return;
- if (!pcpu->governor_enabled) {
- up_read(&pcpu->enable_sem);
- return;
- }
-
- now = ktime_to_us(ktime_get());
- pending = timer_pending(&pcpu->cpu_timer);
-
- if (pcpu->target_freq > pcpu->policy->min ||
- (pcpu->target_freq == pcpu->policy->min &&
- now < boostpulse_endtime)) {
- /*
- * Entering idle while not at lowest speed. On some
- * platforms this can hold the other CPU(s) at that speed
- * even though the CPU is idle. Set a timer to re-evaluate
- * speed so this idle CPU doesn't hold the other CPUs above
- * min indefinitely. This should probably be a quirk of
- * the CPUFreq driver.
- */
- if (!pending) {
- pcpu->last_evaluated_jiffy = get_jiffies_64();
- cpufreq_interactive_timer_resched(smp_processor_id());
-
- /*
- * If timer is cancelled because CPU is running at
- * policy->max, record the time CPU first goes to
- * idle.
- */
- now = ktime_to_us(ktime_get());
- if (max_freq_hysteresis) {
- spin_lock_irqsave(&pcpu->target_freq_lock,
- flags);
- pcpu->max_freq_idle_start_time = now;
- spin_unlock_irqrestore(&pcpu->target_freq_lock,
- flags);
- }
- }
- }
-
- up_read(&pcpu->enable_sem);
-}
-
static void cpufreq_interactive_idle_end(void)
{
struct cpufreq_interactive_cpuinfo *pcpu =
@@ -1120,14 +1062,8 @@ static int cpufreq_interactive_idle_notifier(struct notifier_block *nb,
unsigned long val,
void *data)
{
- switch (val) {
- case IDLE_START:
- cpufreq_interactive_idle_start();
- break;
- case IDLE_END:
+ if (val == IDLE_END)
cpufreq_interactive_idle_end();
- break;
- }
return 0;
}