diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index 6bbcc905bb3e..3f9d8f43fc48 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -49,7 +49,8 @@ struct cpufreq_interactive_cpuinfo { unsigned int floor_freq; unsigned int max_freq; u64 floor_validate_time; - u64 hispeed_validate_time; + u64 pol_hispeed_val_time; /* policy hispeed_validate_time */ + u64 loc_hispeed_val_time; /* per-cpu hispeed_validate_time */ struct rw_semaphore enable_sem; int governor_enabled; }; @@ -367,7 +368,7 @@ static void cpufreq_interactive_timer(unsigned long data) tunables->boosted = tunables->boost_val || now < tunables->boostpulse_endtime; if (cpu_load >= tunables->go_hispeed_load || tunables->boosted) { - if (pcpu->target_freq < tunables->hispeed_freq) { + if (pcpu->policy->cur < tunables->hispeed_freq) { new_freq = tunables->hispeed_freq; } else { new_freq = choose_freq(pcpu, loadadjfreq); @@ -378,14 +379,14 @@ static void cpufreq_interactive_timer(unsigned long data) } else { new_freq = choose_freq(pcpu, loadadjfreq); if (new_freq > tunables->hispeed_freq && - pcpu->target_freq < tunables->hispeed_freq) + pcpu->policy->cur < tunables->hispeed_freq) new_freq = tunables->hispeed_freq; } - if (pcpu->target_freq >= tunables->hispeed_freq && - new_freq > pcpu->target_freq && - now - pcpu->hispeed_validate_time < - freq_to_above_hispeed_delay(tunables, pcpu->target_freq)) { + if (pcpu->policy->cur >= tunables->hispeed_freq && + new_freq > pcpu->policy->cur && + now - pcpu->pol_hispeed_val_time < + freq_to_above_hispeed_delay(tunables, pcpu->policy->cur)) { trace_cpufreq_interactive_notyet( data, cpu_load, pcpu->target_freq, pcpu->policy->cur, new_freq); @@ -393,7 +394,7 @@ static void cpufreq_interactive_timer(unsigned long data) goto rearm; } - pcpu->hispeed_validate_time = now; + pcpu->loc_hispeed_val_time = now; if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table, new_freq, CPUFREQ_RELATION_L, @@ -553,6 +554,8 @@ static int cpufreq_interactive_speedchange_task(void *data) for_each_cpu(cpu, &tmp_mask) { unsigned int j; unsigned int max_freq = 0; + struct cpufreq_interactive_cpuinfo *pjcpu; + u64 hvt = ~0ULL; pcpu = &per_cpu(cpuinfo, cpu); if (!down_read_trylock(&pcpu->enable_sem)) @@ -563,17 +566,25 @@ static int cpufreq_interactive_speedchange_task(void *data) } for_each_cpu(j, pcpu->policy->cpus) { - struct cpufreq_interactive_cpuinfo *pjcpu = - &per_cpu(cpuinfo, j); + pjcpu = &per_cpu(cpuinfo, j); - if (pjcpu->target_freq > max_freq) + if (pjcpu->target_freq > max_freq) { max_freq = pjcpu->target_freq; + hvt = pjcpu->loc_hispeed_val_time; + } else if (pjcpu->target_freq == max_freq) { + hvt = min(hvt, pjcpu->loc_hispeed_val_time); + } } - if (max_freq != pcpu->policy->cur) + if (max_freq != pcpu->policy->cur) { __cpufreq_driver_target(pcpu->policy, max_freq, CPUFREQ_RELATION_H); + for_each_cpu(j, pcpu->policy->cpus) { + pjcpu = &per_cpu(cpuinfo, j); + pjcpu->pol_hispeed_val_time = hvt; + } + } trace_cpufreq_interactive_setspeed(cpu, pcpu->target_freq, pcpu->policy->cur); @@ -605,7 +616,7 @@ static void cpufreq_interactive_boost(struct cpufreq_interactive_tunables *tunab if (pcpu->target_freq < tunables->hispeed_freq) { pcpu->target_freq = tunables->hispeed_freq; cpumask_set_cpu(i, &speedchange_cpumask); - pcpu->hispeed_validate_time = + pcpu->pol_hispeed_val_time = ktime_to_us(ktime_get()); anyboost = 1; } @@ -1234,8 +1245,9 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, pcpu->floor_freq = pcpu->target_freq; pcpu->floor_validate_time = ktime_to_us(ktime_get()); - pcpu->hispeed_validate_time = + pcpu->pol_hispeed_val_time = pcpu->floor_validate_time; + pcpu->loc_hispeed_val_time = pcpu->floor_validate_time; pcpu->max_freq = policy->max; down_write(&pcpu->enable_sem); del_timer_sync(&pcpu->cpu_timer);