aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 437e75924001..8ddb6fcf1f1a 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -48,7 +48,8 @@ struct cpufreq_interactive_cpuinfo {
unsigned int target_freq;
unsigned int floor_freq;
unsigned int max_freq;
- u64 floor_validate_time;
+ u64 pol_floor_val_time; /* policy floor_validate_time */
+ u64 loc_floor_val_time; /* per-cpu floor_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;
@@ -346,6 +347,7 @@ static void cpufreq_interactive_timer(unsigned long data)
unsigned int loadadjfreq;
unsigned int index;
unsigned long flags;
+ u64 max_fvtime;
if (!down_read_trylock(&pcpu->enable_sem))
return;
@@ -409,9 +411,10 @@ static void cpufreq_interactive_timer(unsigned long data)
* Do not scale below floor_freq unless we have been at or above the
* floor frequency for the minimum sample time since last validated.
*/
- if (new_freq < pcpu->floor_freq) {
- if (now - pcpu->floor_validate_time <
- tunables->min_sample_time) {
+ max_fvtime = max(pcpu->pol_floor_val_time, pcpu->loc_floor_val_time);
+ if (new_freq < pcpu->floor_freq &&
+ pcpu->target_freq >= pcpu->policy->cur) {
+ if (now - max_fvtime < tunables->min_sample_time) {
trace_cpufreq_interactive_notyet(
data, cpu_load, pcpu->target_freq,
pcpu->policy->cur, new_freq);
@@ -430,7 +433,9 @@ static void cpufreq_interactive_timer(unsigned long data)
if (!tunables->boosted || new_freq > tunables->hispeed_freq) {
pcpu->floor_freq = new_freq;
- pcpu->floor_validate_time = now;
+ if (pcpu->target_freq >= pcpu->policy->cur ||
+ new_freq >= pcpu->policy->cur)
+ pcpu->loc_floor_val_time = now;
}
if (pcpu->target_freq == new_freq &&
@@ -555,7 +560,7 @@ static int cpufreq_interactive_speedchange_task(void *data)
unsigned int j;
unsigned int max_freq = 0;
struct cpufreq_interactive_cpuinfo *pjcpu;
- u64 hvt = ~0ULL;
+ u64 hvt = ~0ULL, fvt = 0;
pcpu = &per_cpu(cpuinfo, cpu);
if (!down_read_trylock(&pcpu->enable_sem))
@@ -568,6 +573,7 @@ static int cpufreq_interactive_speedchange_task(void *data)
for_each_cpu(j, pcpu->policy->cpus) {
pjcpu = &per_cpu(cpuinfo, j);
+ fvt = max(fvt, pjcpu->loc_floor_val_time);
if (pjcpu->target_freq > max_freq) {
max_freq = pjcpu->target_freq;
hvt = pjcpu->loc_hispeed_val_time;
@@ -575,6 +581,10 @@ static int cpufreq_interactive_speedchange_task(void *data)
hvt = min(hvt, pjcpu->loc_hispeed_val_time);
}
}
+ for_each_cpu(j, pcpu->policy->cpus) {
+ pjcpu = &per_cpu(cpuinfo, j);
+ pjcpu->pol_floor_val_time = fvt;
+ }
if (max_freq != pcpu->policy->cur) {
__cpufreq_driver_target(pcpu->policy,
@@ -1243,11 +1253,11 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
pcpu->target_freq = policy->cur;
pcpu->freq_table = freq_table;
pcpu->floor_freq = pcpu->target_freq;
- pcpu->floor_validate_time =
+ pcpu->pol_floor_val_time =
ktime_to_us(ktime_get());
- pcpu->pol_hispeed_val_time =
- pcpu->floor_validate_time;
- pcpu->loc_hispeed_val_time = pcpu->floor_validate_time;
+ pcpu->loc_floor_val_time = pcpu->pol_floor_val_time;
+ pcpu->pol_hispeed_val_time = pcpu->pol_floor_val_time;
+ pcpu->loc_hispeed_val_time = pcpu->pol_floor_val_time;
pcpu->max_freq = policy->max;
down_write(&pcpu->enable_sem);
del_timer_sync(&pcpu->cpu_timer);