Loading drivers/cpufreq/cpufreq_interactive.c +34 −13 Original line number Diff line number Diff line Loading @@ -46,8 +46,10 @@ struct cpufreq_interactive_cpuinfo { u64 cputime_speedadj_timestamp; struct cpufreq_policy *policy; struct cpufreq_frequency_table *freq_table; spinlock_t target_freq_lock; /*protects target freq */ unsigned int target_freq; unsigned int floor_freq; unsigned int max_freq; u64 floor_validate_time; u64 hispeed_validate_time; struct rw_semaphore enable_sem; Loading Loading @@ -385,6 +387,7 @@ static void cpufreq_interactive_timer(unsigned long data) if (WARN_ON_ONCE(!delta_time)) goto rearm; spin_lock_irqsave(&pcpu->target_freq_lock, flags); do_div(cputime_speedadj, delta_time); loadadjfreq = (unsigned int)cputime_speedadj * 100; cpu_load = loadadjfreq / pcpu->target_freq; Loading Loading @@ -432,6 +435,7 @@ static void cpufreq_interactive_timer(unsigned long data) trace_cpufreq_interactive_notyet( data, cpu_load, pcpu->target_freq, pcpu->policy->cur, new_freq); spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); goto rearm; } Loading @@ -439,8 +443,10 @@ static void cpufreq_interactive_timer(unsigned long data) if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table, new_freq, CPUFREQ_RELATION_L, &index)) &index)) { spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); goto rearm; } new_freq = pcpu->freq_table[index].frequency; Loading @@ -467,6 +473,7 @@ static void cpufreq_interactive_timer(unsigned long data) trace_cpufreq_interactive_notyet( data, cpu_load, pcpu->target_freq, pcpu->policy->cur, new_freq); spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); goto rearm; } } Loading @@ -488,6 +495,7 @@ static void cpufreq_interactive_timer(unsigned long data) 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; } Loading @@ -495,6 +503,7 @@ static void cpufreq_interactive_timer(unsigned long data) pcpu->policy->cur, new_freq); pcpu->target_freq = new_freq; spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); spin_lock_irqsave(&speedchange_cpumask_lock, flags); cpumask_set_cpu(data, &speedchange_cpumask); spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); Loading Loading @@ -648,16 +657,17 @@ static void cpufreq_interactive_boost(void) { int i; int anyboost = 0; unsigned long flags; unsigned long flags[2]; struct cpufreq_interactive_cpuinfo *pcpu; struct cpufreq_interactive_tunables *tunables; spin_lock_irqsave(&speedchange_cpumask_lock, flags); spin_lock_irqsave(&speedchange_cpumask_lock, flags[0]); for_each_online_cpu(i) { pcpu = &per_cpu(cpuinfo, i); tunables = pcpu->policy->governor_data; spin_lock_irqsave(&pcpu->target_freq_lock, flags[1]); if (pcpu->target_freq < tunables->hispeed_freq) { pcpu->target_freq = tunables->hispeed_freq; cpumask_set_cpu(i, &speedchange_cpumask); Loading @@ -673,9 +683,10 @@ static void cpufreq_interactive_boost(void) pcpu->floor_freq = tunables->hispeed_freq; pcpu->floor_validate_time = ktime_to_us(ktime_get()); spin_unlock_irqrestore(&pcpu->target_freq_lock, flags[1]); } spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); spin_unlock_irqrestore(&speedchange_cpumask_lock, flags[0]); if (anyboost) wake_up_process(speedchange_task); Loading Loading @@ -1274,6 +1285,7 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, struct cpufreq_interactive_cpuinfo *pcpu; struct cpufreq_frequency_table *freq_table; struct cpufreq_interactive_tunables *tunables; unsigned long flags; if (have_governor_per_policy()) tunables = policy->governor_data; Loading Loading @@ -1362,6 +1374,7 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, ktime_to_us(ktime_get()); pcpu->hispeed_validate_time = pcpu->floor_validate_time; pcpu->max_freq = policy->max; down_write(&pcpu->enable_sem); del_timer_sync(&pcpu->cpu_timer); del_timer_sync(&pcpu->cpu_slack_timer); Loading Loading @@ -1398,30 +1411,37 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, for_each_cpu(j, policy->cpus) { pcpu = &per_cpu(cpuinfo, j); /* hold write semaphore to avoid race */ down_write(&pcpu->enable_sem); down_read(&pcpu->enable_sem); if (pcpu->governor_enabled == 0) { up_write(&pcpu->enable_sem); up_read(&pcpu->enable_sem); continue; } /* update target_freq firstly */ spin_lock_irqsave(&pcpu->target_freq_lock, flags); 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. spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); up_read(&pcpu->enable_sem); /* Reschedule timer only if policy->max is raised. * 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. */ if (policy->max > pcpu->max_freq) { down_write(&pcpu->enable_sem); del_timer_sync(&pcpu->cpu_timer); del_timer_sync(&pcpu->cpu_slack_timer); cpufreq_interactive_timer_start(tunables, j); up_write(&pcpu->enable_sem); } pcpu->max_freq = policy->max; pcpu->limits_changed = true; } break; Loading Loading @@ -1458,6 +1478,7 @@ static int __init cpufreq_interactive_init(void) init_timer(&pcpu->cpu_slack_timer); pcpu->cpu_slack_timer.function = cpufreq_interactive_nop_timer; spin_lock_init(&pcpu->load_lock); spin_lock_init(&pcpu->target_freq_lock); init_rwsem(&pcpu->enable_sem); } Loading Loading
drivers/cpufreq/cpufreq_interactive.c +34 −13 Original line number Diff line number Diff line Loading @@ -46,8 +46,10 @@ struct cpufreq_interactive_cpuinfo { u64 cputime_speedadj_timestamp; struct cpufreq_policy *policy; struct cpufreq_frequency_table *freq_table; spinlock_t target_freq_lock; /*protects target freq */ unsigned int target_freq; unsigned int floor_freq; unsigned int max_freq; u64 floor_validate_time; u64 hispeed_validate_time; struct rw_semaphore enable_sem; Loading Loading @@ -385,6 +387,7 @@ static void cpufreq_interactive_timer(unsigned long data) if (WARN_ON_ONCE(!delta_time)) goto rearm; spin_lock_irqsave(&pcpu->target_freq_lock, flags); do_div(cputime_speedadj, delta_time); loadadjfreq = (unsigned int)cputime_speedadj * 100; cpu_load = loadadjfreq / pcpu->target_freq; Loading Loading @@ -432,6 +435,7 @@ static void cpufreq_interactive_timer(unsigned long data) trace_cpufreq_interactive_notyet( data, cpu_load, pcpu->target_freq, pcpu->policy->cur, new_freq); spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); goto rearm; } Loading @@ -439,8 +443,10 @@ static void cpufreq_interactive_timer(unsigned long data) if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table, new_freq, CPUFREQ_RELATION_L, &index)) &index)) { spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); goto rearm; } new_freq = pcpu->freq_table[index].frequency; Loading @@ -467,6 +473,7 @@ static void cpufreq_interactive_timer(unsigned long data) trace_cpufreq_interactive_notyet( data, cpu_load, pcpu->target_freq, pcpu->policy->cur, new_freq); spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); goto rearm; } } Loading @@ -488,6 +495,7 @@ static void cpufreq_interactive_timer(unsigned long data) 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; } Loading @@ -495,6 +503,7 @@ static void cpufreq_interactive_timer(unsigned long data) pcpu->policy->cur, new_freq); pcpu->target_freq = new_freq; spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); spin_lock_irqsave(&speedchange_cpumask_lock, flags); cpumask_set_cpu(data, &speedchange_cpumask); spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); Loading Loading @@ -648,16 +657,17 @@ static void cpufreq_interactive_boost(void) { int i; int anyboost = 0; unsigned long flags; unsigned long flags[2]; struct cpufreq_interactive_cpuinfo *pcpu; struct cpufreq_interactive_tunables *tunables; spin_lock_irqsave(&speedchange_cpumask_lock, flags); spin_lock_irqsave(&speedchange_cpumask_lock, flags[0]); for_each_online_cpu(i) { pcpu = &per_cpu(cpuinfo, i); tunables = pcpu->policy->governor_data; spin_lock_irqsave(&pcpu->target_freq_lock, flags[1]); if (pcpu->target_freq < tunables->hispeed_freq) { pcpu->target_freq = tunables->hispeed_freq; cpumask_set_cpu(i, &speedchange_cpumask); Loading @@ -673,9 +683,10 @@ static void cpufreq_interactive_boost(void) pcpu->floor_freq = tunables->hispeed_freq; pcpu->floor_validate_time = ktime_to_us(ktime_get()); spin_unlock_irqrestore(&pcpu->target_freq_lock, flags[1]); } spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); spin_unlock_irqrestore(&speedchange_cpumask_lock, flags[0]); if (anyboost) wake_up_process(speedchange_task); Loading Loading @@ -1274,6 +1285,7 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, struct cpufreq_interactive_cpuinfo *pcpu; struct cpufreq_frequency_table *freq_table; struct cpufreq_interactive_tunables *tunables; unsigned long flags; if (have_governor_per_policy()) tunables = policy->governor_data; Loading Loading @@ -1362,6 +1374,7 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, ktime_to_us(ktime_get()); pcpu->hispeed_validate_time = pcpu->floor_validate_time; pcpu->max_freq = policy->max; down_write(&pcpu->enable_sem); del_timer_sync(&pcpu->cpu_timer); del_timer_sync(&pcpu->cpu_slack_timer); Loading Loading @@ -1398,30 +1411,37 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, for_each_cpu(j, policy->cpus) { pcpu = &per_cpu(cpuinfo, j); /* hold write semaphore to avoid race */ down_write(&pcpu->enable_sem); down_read(&pcpu->enable_sem); if (pcpu->governor_enabled == 0) { up_write(&pcpu->enable_sem); up_read(&pcpu->enable_sem); continue; } /* update target_freq firstly */ spin_lock_irqsave(&pcpu->target_freq_lock, flags); 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. spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); up_read(&pcpu->enable_sem); /* Reschedule timer only if policy->max is raised. * 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. */ if (policy->max > pcpu->max_freq) { down_write(&pcpu->enable_sem); del_timer_sync(&pcpu->cpu_timer); del_timer_sync(&pcpu->cpu_slack_timer); cpufreq_interactive_timer_start(tunables, j); up_write(&pcpu->enable_sem); } pcpu->max_freq = policy->max; pcpu->limits_changed = true; } break; Loading Loading @@ -1458,6 +1478,7 @@ static int __init cpufreq_interactive_init(void) init_timer(&pcpu->cpu_slack_timer); pcpu->cpu_slack_timer.function = cpufreq_interactive_nop_timer; spin_lock_init(&pcpu->load_lock); spin_lock_init(&pcpu->target_freq_lock); init_rwsem(&pcpu->enable_sem); } Loading