Loading drivers/cpufreq/cpufreq_interactive.c +47 −41 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ struct cpufreq_interactive_policyinfo { spinlock_t load_lock; /* protects load tracking stat */ u64 last_evaluated_jiffy; struct cpufreq_policy *policy; struct cpufreq_policy p_nolim; /* policy copy with no limits */ struct cpufreq_frequency_table *freq_table; spinlock_t target_freq_lock; /*protects target freq */ unsigned int target_freq; Loading Loading @@ -339,7 +340,7 @@ static unsigned int choose_freq(struct cpufreq_interactive_policyinfo *pcpu, */ if (cpufreq_frequency_table_target( pcpu->policy, pcpu->freq_table, loadadjfreq / tl, &pcpu->p_nolim, pcpu->freq_table, loadadjfreq / tl, CPUFREQ_RELATION_L, &index)) break; freq = pcpu->freq_table[index].frequency; Loading @@ -354,7 +355,7 @@ static unsigned int choose_freq(struct cpufreq_interactive_policyinfo *pcpu, * than freqmax. */ if (cpufreq_frequency_table_target( pcpu->policy, pcpu->freq_table, &pcpu->p_nolim, pcpu->freq_table, freqmax - 1, CPUFREQ_RELATION_H, &index)) break; Loading @@ -381,7 +382,7 @@ static unsigned int choose_freq(struct cpufreq_interactive_policyinfo *pcpu, * than freqmin. */ if (cpufreq_frequency_table_target( pcpu->policy, pcpu->freq_table, &pcpu->p_nolim, pcpu->freq_table, freqmin + 1, CPUFREQ_RELATION_L, &index)) break; Loading Loading @@ -431,6 +432,7 @@ static u64 update_load(int cpu) return now; } #define NEW_TASK_RATIO 75 static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) { u64 now; Loading @@ -448,9 +450,11 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) unsigned long max_cpu; int i, fcpu; struct sched_load *sl; int new_load_pct = 0; struct cpufreq_govinfo govinfo; bool skip_hispeed_logic, skip_min_sample_time; bool policy_max_fast_restore = false; bool jump_to_max = false; if (!down_read_trylock(&ppol->enable_sem)) return; Loading @@ -458,8 +462,12 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) goto exit; fcpu = cpumask_first(ppol->policy->related_cpus); skip_hispeed_logic = tunables->ignore_hispeed_on_notif && is_notif; skip_min_sample_time = tunables->fast_ramp_down && is_notif; now = ktime_to_us(ktime_get()); spin_lock_irqsave(&ppol->load_lock, flags); spin_lock_irqsave(&ppol->target_freq_lock, flags); spin_lock(&ppol->load_lock); ppol->last_evaluated_jiffy = get_jiffies_64(); if (tunables->use_sched_load) Loading @@ -472,6 +480,7 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) cputime_speedadj = (u64)sl->prev_load * ppol->policy->cpuinfo.max_freq; do_div(cputime_speedadj, tunables->timer_rate); new_load_pct = sl->new_task_load * 100 / sl->prev_load; } else { now = update_load(i); delta_time = (unsigned int) Loading @@ -483,38 +492,25 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) } tmploadadjfreq = (unsigned int)cputime_speedadj * 100; pcpu->loadadjfreq = tmploadadjfreq; trace_cpufreq_interactive_cpuload(i, tmploadadjfreq / ppol->target_freq); if (tmploadadjfreq > loadadjfreq) { loadadjfreq = tmploadadjfreq; max_cpu = i; } } spin_unlock_irqrestore(&ppol->load_lock, flags); cpu_load = tmploadadjfreq / ppol->target_freq; trace_cpufreq_interactive_cpuload(i, cpu_load, new_load_pct); /* * Send govinfo notification. * Govinfo notification could potentially wake up another thread * managed by its clients. Thread wakeups might trigger a load * change callback that executes this function again. Therefore * no spinlock could be held when sending the notification. */ for_each_cpu(i, ppol->policy->cpus) { pcpu = &per_cpu(cpuinfo, i); govinfo.cpu = i; govinfo.load = pcpu->loadadjfreq / ppol->policy->max; govinfo.sampling_rate_us = tunables->timer_rate; atomic_notifier_call_chain(&cpufreq_govinfo_notifier_list, CPUFREQ_LOAD_CHANGE, &govinfo); if (cpu_load >= tunables->go_hispeed_load && new_load_pct >= NEW_TASK_RATIO) { skip_hispeed_logic = true; jump_to_max = true; } } spin_unlock(&ppol->load_lock); spin_lock_irqsave(&ppol->target_freq_lock, flags); cpu_load = loadadjfreq / ppol->target_freq; tunables->boosted = tunables->boost_val || now < tunables->boostpulse_endtime; skip_hispeed_logic = tunables->ignore_hispeed_on_notif && is_notif; skip_min_sample_time = tunables->fast_ramp_down && is_notif; if (now - ppol->max_freq_hyst_start_time < tunables->max_freq_hysteresis && cpu_load >= tunables->go_hispeed_load && Loading @@ -524,8 +520,8 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) policy_max_fast_restore = true; } if (policy_max_fast_restore) { new_freq = ppol->policy->max; if (policy_max_fast_restore || jump_to_max) { new_freq = ppol->policy->cpuinfo.max_freq; } else if (skip_hispeed_logic) { new_freq = choose_freq(ppol, loadadjfreq); } else if (cpu_load >= tunables->go_hispeed_load || tunables->boosted) { Loading Loading @@ -562,7 +558,7 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) ppol->hispeed_validate_time = now; if (cpufreq_frequency_table_target(ppol->policy, ppol->freq_table, if (cpufreq_frequency_table_target(&ppol->p_nolim, ppol->freq_table, new_freq, CPUFREQ_RELATION_L, &index)) { spin_unlock_irqrestore(&ppol->target_freq_lock, flags); Loading Loading @@ -603,7 +599,7 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) ppol->floor_validate_time = now; } if (new_freq == ppol->policy->max && !policy_max_fast_restore) if (new_freq >= ppol->policy->max && !policy_max_fast_restore) ppol->max_freq_hyst_start_time = now; if (ppol->target_freq == new_freq && Loading @@ -629,6 +625,22 @@ rearm: if (!timer_pending(&ppol->policy_timer)) cpufreq_interactive_timer_resched(data, false); /* * Send govinfo notification. * Govinfo notification could potentially wake up another thread * managed by its clients. Thread wakeups might trigger a load * change callback that executes this function again. Therefore * no spinlock could be held when sending the notification. */ for_each_cpu(i, ppol->policy->cpus) { pcpu = &per_cpu(cpuinfo, i); govinfo.cpu = i; govinfo.load = pcpu->loadadjfreq / ppol->policy->max; govinfo.sampling_rate_us = tunables->timer_rate; atomic_notifier_call_chain(&cpufreq_govinfo_notifier_list, CPUFREQ_LOAD_CHANGE, &govinfo); } exit: up_read(&ppol->enable_sem); return; Loading Loading @@ -1568,7 +1580,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, struct cpufreq_interactive_policyinfo *ppol; 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 @@ -1673,6 +1684,9 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, ppol->policy = policy; ppol->target_freq = policy->cur; ppol->freq_table = freq_table; ppol->p_nolim = *policy; ppol->p_nolim.min = policy->cpuinfo.min_freq; ppol->p_nolim.max = policy->cpuinfo.max_freq; ppol->floor_freq = ppol->target_freq; ppol->floor_validate_time = ktime_to_us(ktime_get()); ppol->hispeed_validate_time = ppol->floor_validate_time; Loading Loading @@ -1708,26 +1722,18 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, break; case CPUFREQ_GOV_LIMITS: __cpufreq_driver_target(policy, policy->cur, CPUFREQ_RELATION_L); ppol = per_cpu(polinfo, policy->cpu); __cpufreq_driver_target(policy, ppol->target_freq, CPUFREQ_RELATION_L); down_read(&ppol->enable_sem); if (ppol->governor_enabled) { spin_lock_irqsave(&ppol->target_freq_lock, flags); if (policy->max < ppol->target_freq) ppol->target_freq = policy->max; else if (policy->min > ppol->target_freq) ppol->target_freq = policy->min; spin_unlock_irqrestore(&ppol->target_freq_lock, flags); if (policy->min < ppol->min_freq) cpufreq_interactive_timer_resched(policy->cpu, true); ppol->min_freq = policy->min; } up_read(&ppol->enable_sem); break; Loading include/trace/events/cpufreq_interactive.h +7 −3 Original line number Diff line number Diff line Loading @@ -119,17 +119,21 @@ TRACE_EVENT(cpufreq_interactive_load_change, ); TRACE_EVENT(cpufreq_interactive_cpuload, TP_PROTO(unsigned long cpu_id, unsigned long load), TP_ARGS(cpu_id, load), TP_PROTO(unsigned long cpu_id, unsigned long load, unsigned int new_task_pct), TP_ARGS(cpu_id, load, new_task_pct), TP_STRUCT__entry( __field(unsigned long, cpu_id) __field(unsigned long, load) __field(unsigned long, new_task_pct) ), TP_fast_assign( __entry->cpu_id = cpu_id; __entry->load = load; __entry->new_task_pct = new_task_pct; ), TP_printk("cpu=%lu load=%lu", __entry->cpu_id, __entry->load) TP_printk("cpu=%lu load=%lu new_task_pct=%lu", __entry->cpu_id, __entry->load, __entry->new_task_pct) ); #endif /* _TRACE_CPUFREQ_INTERACTIVE_H */ Loading Loading
drivers/cpufreq/cpufreq_interactive.c +47 −41 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ struct cpufreq_interactive_policyinfo { spinlock_t load_lock; /* protects load tracking stat */ u64 last_evaluated_jiffy; struct cpufreq_policy *policy; struct cpufreq_policy p_nolim; /* policy copy with no limits */ struct cpufreq_frequency_table *freq_table; spinlock_t target_freq_lock; /*protects target freq */ unsigned int target_freq; Loading Loading @@ -339,7 +340,7 @@ static unsigned int choose_freq(struct cpufreq_interactive_policyinfo *pcpu, */ if (cpufreq_frequency_table_target( pcpu->policy, pcpu->freq_table, loadadjfreq / tl, &pcpu->p_nolim, pcpu->freq_table, loadadjfreq / tl, CPUFREQ_RELATION_L, &index)) break; freq = pcpu->freq_table[index].frequency; Loading @@ -354,7 +355,7 @@ static unsigned int choose_freq(struct cpufreq_interactive_policyinfo *pcpu, * than freqmax. */ if (cpufreq_frequency_table_target( pcpu->policy, pcpu->freq_table, &pcpu->p_nolim, pcpu->freq_table, freqmax - 1, CPUFREQ_RELATION_H, &index)) break; Loading @@ -381,7 +382,7 @@ static unsigned int choose_freq(struct cpufreq_interactive_policyinfo *pcpu, * than freqmin. */ if (cpufreq_frequency_table_target( pcpu->policy, pcpu->freq_table, &pcpu->p_nolim, pcpu->freq_table, freqmin + 1, CPUFREQ_RELATION_L, &index)) break; Loading Loading @@ -431,6 +432,7 @@ static u64 update_load(int cpu) return now; } #define NEW_TASK_RATIO 75 static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) { u64 now; Loading @@ -448,9 +450,11 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) unsigned long max_cpu; int i, fcpu; struct sched_load *sl; int new_load_pct = 0; struct cpufreq_govinfo govinfo; bool skip_hispeed_logic, skip_min_sample_time; bool policy_max_fast_restore = false; bool jump_to_max = false; if (!down_read_trylock(&ppol->enable_sem)) return; Loading @@ -458,8 +462,12 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) goto exit; fcpu = cpumask_first(ppol->policy->related_cpus); skip_hispeed_logic = tunables->ignore_hispeed_on_notif && is_notif; skip_min_sample_time = tunables->fast_ramp_down && is_notif; now = ktime_to_us(ktime_get()); spin_lock_irqsave(&ppol->load_lock, flags); spin_lock_irqsave(&ppol->target_freq_lock, flags); spin_lock(&ppol->load_lock); ppol->last_evaluated_jiffy = get_jiffies_64(); if (tunables->use_sched_load) Loading @@ -472,6 +480,7 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) cputime_speedadj = (u64)sl->prev_load * ppol->policy->cpuinfo.max_freq; do_div(cputime_speedadj, tunables->timer_rate); new_load_pct = sl->new_task_load * 100 / sl->prev_load; } else { now = update_load(i); delta_time = (unsigned int) Loading @@ -483,38 +492,25 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) } tmploadadjfreq = (unsigned int)cputime_speedadj * 100; pcpu->loadadjfreq = tmploadadjfreq; trace_cpufreq_interactive_cpuload(i, tmploadadjfreq / ppol->target_freq); if (tmploadadjfreq > loadadjfreq) { loadadjfreq = tmploadadjfreq; max_cpu = i; } } spin_unlock_irqrestore(&ppol->load_lock, flags); cpu_load = tmploadadjfreq / ppol->target_freq; trace_cpufreq_interactive_cpuload(i, cpu_load, new_load_pct); /* * Send govinfo notification. * Govinfo notification could potentially wake up another thread * managed by its clients. Thread wakeups might trigger a load * change callback that executes this function again. Therefore * no spinlock could be held when sending the notification. */ for_each_cpu(i, ppol->policy->cpus) { pcpu = &per_cpu(cpuinfo, i); govinfo.cpu = i; govinfo.load = pcpu->loadadjfreq / ppol->policy->max; govinfo.sampling_rate_us = tunables->timer_rate; atomic_notifier_call_chain(&cpufreq_govinfo_notifier_list, CPUFREQ_LOAD_CHANGE, &govinfo); if (cpu_load >= tunables->go_hispeed_load && new_load_pct >= NEW_TASK_RATIO) { skip_hispeed_logic = true; jump_to_max = true; } } spin_unlock(&ppol->load_lock); spin_lock_irqsave(&ppol->target_freq_lock, flags); cpu_load = loadadjfreq / ppol->target_freq; tunables->boosted = tunables->boost_val || now < tunables->boostpulse_endtime; skip_hispeed_logic = tunables->ignore_hispeed_on_notif && is_notif; skip_min_sample_time = tunables->fast_ramp_down && is_notif; if (now - ppol->max_freq_hyst_start_time < tunables->max_freq_hysteresis && cpu_load >= tunables->go_hispeed_load && Loading @@ -524,8 +520,8 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) policy_max_fast_restore = true; } if (policy_max_fast_restore) { new_freq = ppol->policy->max; if (policy_max_fast_restore || jump_to_max) { new_freq = ppol->policy->cpuinfo.max_freq; } else if (skip_hispeed_logic) { new_freq = choose_freq(ppol, loadadjfreq); } else if (cpu_load >= tunables->go_hispeed_load || tunables->boosted) { Loading Loading @@ -562,7 +558,7 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) ppol->hispeed_validate_time = now; if (cpufreq_frequency_table_target(ppol->policy, ppol->freq_table, if (cpufreq_frequency_table_target(&ppol->p_nolim, ppol->freq_table, new_freq, CPUFREQ_RELATION_L, &index)) { spin_unlock_irqrestore(&ppol->target_freq_lock, flags); Loading Loading @@ -603,7 +599,7 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) ppol->floor_validate_time = now; } if (new_freq == ppol->policy->max && !policy_max_fast_restore) if (new_freq >= ppol->policy->max && !policy_max_fast_restore) ppol->max_freq_hyst_start_time = now; if (ppol->target_freq == new_freq && Loading @@ -629,6 +625,22 @@ rearm: if (!timer_pending(&ppol->policy_timer)) cpufreq_interactive_timer_resched(data, false); /* * Send govinfo notification. * Govinfo notification could potentially wake up another thread * managed by its clients. Thread wakeups might trigger a load * change callback that executes this function again. Therefore * no spinlock could be held when sending the notification. */ for_each_cpu(i, ppol->policy->cpus) { pcpu = &per_cpu(cpuinfo, i); govinfo.cpu = i; govinfo.load = pcpu->loadadjfreq / ppol->policy->max; govinfo.sampling_rate_us = tunables->timer_rate; atomic_notifier_call_chain(&cpufreq_govinfo_notifier_list, CPUFREQ_LOAD_CHANGE, &govinfo); } exit: up_read(&ppol->enable_sem); return; Loading Loading @@ -1568,7 +1580,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, struct cpufreq_interactive_policyinfo *ppol; 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 @@ -1673,6 +1684,9 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, ppol->policy = policy; ppol->target_freq = policy->cur; ppol->freq_table = freq_table; ppol->p_nolim = *policy; ppol->p_nolim.min = policy->cpuinfo.min_freq; ppol->p_nolim.max = policy->cpuinfo.max_freq; ppol->floor_freq = ppol->target_freq; ppol->floor_validate_time = ktime_to_us(ktime_get()); ppol->hispeed_validate_time = ppol->floor_validate_time; Loading Loading @@ -1708,26 +1722,18 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, break; case CPUFREQ_GOV_LIMITS: __cpufreq_driver_target(policy, policy->cur, CPUFREQ_RELATION_L); ppol = per_cpu(polinfo, policy->cpu); __cpufreq_driver_target(policy, ppol->target_freq, CPUFREQ_RELATION_L); down_read(&ppol->enable_sem); if (ppol->governor_enabled) { spin_lock_irqsave(&ppol->target_freq_lock, flags); if (policy->max < ppol->target_freq) ppol->target_freq = policy->max; else if (policy->min > ppol->target_freq) ppol->target_freq = policy->min; spin_unlock_irqrestore(&ppol->target_freq_lock, flags); if (policy->min < ppol->min_freq) cpufreq_interactive_timer_resched(policy->cpu, true); ppol->min_freq = policy->min; } up_read(&ppol->enable_sem); break; Loading
include/trace/events/cpufreq_interactive.h +7 −3 Original line number Diff line number Diff line Loading @@ -119,17 +119,21 @@ TRACE_EVENT(cpufreq_interactive_load_change, ); TRACE_EVENT(cpufreq_interactive_cpuload, TP_PROTO(unsigned long cpu_id, unsigned long load), TP_ARGS(cpu_id, load), TP_PROTO(unsigned long cpu_id, unsigned long load, unsigned int new_task_pct), TP_ARGS(cpu_id, load, new_task_pct), TP_STRUCT__entry( __field(unsigned long, cpu_id) __field(unsigned long, load) __field(unsigned long, new_task_pct) ), TP_fast_assign( __entry->cpu_id = cpu_id; __entry->load = load; __entry->new_task_pct = new_task_pct; ), TP_printk("cpu=%lu load=%lu", __entry->cpu_id, __entry->load) TP_printk("cpu=%lu load=%lu new_task_pct=%lu", __entry->cpu_id, __entry->load, __entry->new_task_pct) ); #endif /* _TRACE_CPUFREQ_INTERACTIVE_H */ Loading