diff options
| author | Rohit Gupta <rohgup@codeaurora.org> | 2015-03-06 18:46:04 -0800 |
|---|---|---|
| committer | Steve Kondik <shade@chemlab.org> | 2015-05-03 08:41:25 +0000 |
| commit | 493c3a1b582ff4c9987d179c6e3a710269c74177 (patch) | |
| tree | 836d6718cbd5649ae673eebcebc3d592a72f7bc4 | |
| parent | b092e186be01f2ee450be28797cc1cc6e1f006d8 (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.c | 80 |
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; } |
