cpufreq: interactive: resched timer if max freq raised
When the policy max freq is raised, and before the timer is rescheduled in idle callback, the cpu freq may stuck at a lower freq. The target_freq shall be updated too, else on a high load situation, the new_freq is always equal to target_freq and which will cause freq stuck at a lower freq too. Reschedule the timer on gov limits callback. Change-Id: I6c187001ab43e859731429b64f75a74eebc37a24 Signed-off-by: Lianwei Wang <a22439@motorola.com> Git-commit: 0edc2b4c9c30a695d9500d3204acdf5f3ddfa027 Git-repo: https://android.googlesource.com/kernel/common/ Signed-off-by: Dilip Gudlur <dgudlur@codeaurora.org>
This commit is contained in:
parent
350048f773
commit
d854171db0
|
@ -188,6 +188,32 @@ static void cpufreq_interactive_timer_resched(
|
|||
spin_unlock_irqrestore(&pcpu->load_lock, flags);
|
||||
}
|
||||
|
||||
/* The caller shall take enable_sem write semaphore to avoid any timer race.
|
||||
* The cpu_timer and cpu_slack_timer must be deactivated when calling this
|
||||
* function.
|
||||
*/
|
||||
static void cpufreq_interactive_timer_start(int cpu)
|
||||
{
|
||||
struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu);
|
||||
unsigned long expires = jiffies + usecs_to_jiffies(timer_rate);
|
||||
unsigned long flags;
|
||||
|
||||
pcpu->cpu_timer.expires = expires;
|
||||
add_timer_on(&pcpu->cpu_timer, cpu);
|
||||
if (timer_slack_val >= 0 && pcpu->target_freq > pcpu->policy->min) {
|
||||
expires += usecs_to_jiffies(timer_slack_val);
|
||||
pcpu->cpu_slack_timer.expires = expires;
|
||||
add_timer_on(&pcpu->cpu_slack_timer, cpu);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&pcpu->load_lock, flags);
|
||||
pcpu->time_in_idle =
|
||||
get_cpu_idle_time(cpu, &pcpu->time_in_idle_timestamp);
|
||||
pcpu->cputime_speedadj = 0;
|
||||
pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp;
|
||||
spin_unlock_irqrestore(&pcpu->load_lock, flags);
|
||||
}
|
||||
|
||||
static unsigned int freq_to_above_hispeed_delay(unsigned int freq)
|
||||
{
|
||||
int i;
|
||||
|
@ -1057,8 +1083,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
|
|||
hispeed_freq = policy->max;
|
||||
|
||||
for_each_cpu(j, policy->cpus) {
|
||||
unsigned long expires;
|
||||
|
||||
pcpu = &per_cpu(cpuinfo, j);
|
||||
pcpu->policy = policy;
|
||||
pcpu->target_freq = policy->cur;
|
||||
|
@ -1069,14 +1093,7 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
|
|||
pcpu->hispeed_validate_time =
|
||||
pcpu->floor_validate_time;
|
||||
down_write(&pcpu->enable_sem);
|
||||
expires = jiffies + usecs_to_jiffies(timer_rate);
|
||||
pcpu->cpu_timer.expires = expires;
|
||||
add_timer_on(&pcpu->cpu_timer, j);
|
||||
if (timer_slack_val >= 0) {
|
||||
expires += usecs_to_jiffies(timer_slack_val);
|
||||
pcpu->cpu_slack_timer.expires = expires;
|
||||
add_timer_on(&pcpu->cpu_slack_timer, j);
|
||||
}
|
||||
cpufreq_interactive_timer_start(j);
|
||||
pcpu->governor_enabled = 1;
|
||||
up_write(&pcpu->enable_sem);
|
||||
}
|
||||
|
@ -1135,6 +1152,33 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
|
|||
else if (policy->min > policy->cur)
|
||||
__cpufreq_driver_target(policy,
|
||||
policy->min, CPUFREQ_RELATION_L);
|
||||
for_each_cpu(j, policy->cpus) {
|
||||
pcpu = &per_cpu(cpuinfo, j);
|
||||
|
||||
/* hold write semaphore to avoid race */
|
||||
down_write(&pcpu->enable_sem);
|
||||
if (pcpu->governor_enabled == 0) {
|
||||
up_write(&pcpu->enable_sem);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* update target_freq firstly */
|
||||
if (policy->max < pcpu->target_freq)
|
||||
pcpu->target_freq = policy->max;
|
||||
else if (policy->min > pcpu->target_freq)
|
||||
pcpu->target_freq = policy->min;
|
||||
|
||||
/* Reschedule timer.
|
||||
* Delete the timers, else the timer callback may
|
||||
* return without re-arm the timer when failed
|
||||
* acquire the semaphore. This race may cause timer
|
||||
* stopped unexpectedly.
|
||||
*/
|
||||
del_timer_sync(&pcpu->cpu_timer);
|
||||
del_timer_sync(&pcpu->cpu_slack_timer);
|
||||
cpufreq_interactive_timer_start(j);
|
||||
up_write(&pcpu->enable_sem);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue