Merge branch 'pm-cpufreq'
* pm-cpufreq: (41 commits) Revert "cpufreq: pcc-cpufreq: update default value of cpuinfo_transition_latency" cpufreq: export cpufreq_driver_resolve_freq() cpufreq: Disallow ->resolve_freq() for drivers providing ->target_index() cpufreq: acpi-cpufreq: use cached frequency mapping when possible cpufreq: schedutil: map raw required frequency to driver frequency cpufreq: add cpufreq_driver_resolve_freq() cpufreq: intel_pstate: Check cpuid for MSR_HWP_INTERRUPT intel_pstate: Update cpu_frequency tracepoint every time cpufreq: intel_pstate: clean remnant struct element cpufreq: powernv: Replacing pstate_id with frequency table index intel_pstate: Fix MSR_CONFIG_TDP_x addressing in core_get_max_pstate() cpufreq: Reuse new freq-table helpers cpufreq: Handle sorted frequency tables more efficiently cpufreq: Drop redundant check from cpufreq_update_current_freq() intel_pstate: Declare pid_params/pstate_funcs/hwp_active __read_mostly intel_pstate: add __init/__initdata marker to some functions/variables intel_pstate: Fix incorrect placement of __initdata cpufreq: mvebu: fix integer to pointer cast cpufreq: intel_pstate: Broxton support cpufreq: conservative: Do not use transition notifications ...
This commit is contained in:
@@ -47,6 +47,8 @@ struct sugov_cpu {
|
||||
struct update_util_data update_util;
|
||||
struct sugov_policy *sg_policy;
|
||||
|
||||
unsigned int cached_raw_freq;
|
||||
|
||||
/* The fields below are only needed when sharing a policy. */
|
||||
unsigned long util;
|
||||
unsigned long max;
|
||||
@@ -106,7 +108,7 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time,
|
||||
|
||||
/**
|
||||
* get_next_freq - Compute a new frequency for a given cpufreq policy.
|
||||
* @policy: cpufreq policy object to compute the new frequency for.
|
||||
* @sg_cpu: schedutil cpu object to compute the new frequency for.
|
||||
* @util: Current CPU utilization.
|
||||
* @max: CPU capacity.
|
||||
*
|
||||
@@ -121,14 +123,25 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time,
|
||||
* next_freq = C * curr_freq * util_raw / max
|
||||
*
|
||||
* Take C = 1.25 for the frequency tipping point at (util / max) = 0.8.
|
||||
*
|
||||
* The lowest driver-supported frequency which is equal or greater than the raw
|
||||
* next_freq (as calculated above) is returned, subject to policy min/max and
|
||||
* cpufreq driver limitations.
|
||||
*/
|
||||
static unsigned int get_next_freq(struct cpufreq_policy *policy,
|
||||
unsigned long util, unsigned long max)
|
||||
static unsigned int get_next_freq(struct sugov_cpu *sg_cpu, unsigned long util,
|
||||
unsigned long max)
|
||||
{
|
||||
struct sugov_policy *sg_policy = sg_cpu->sg_policy;
|
||||
struct cpufreq_policy *policy = sg_policy->policy;
|
||||
unsigned int freq = arch_scale_freq_invariant() ?
|
||||
policy->cpuinfo.max_freq : policy->cur;
|
||||
|
||||
return (freq + (freq >> 2)) * util / max;
|
||||
freq = (freq + (freq >> 2)) * util / max;
|
||||
|
||||
if (freq == sg_cpu->cached_raw_freq && sg_policy->next_freq != UINT_MAX)
|
||||
return sg_policy->next_freq;
|
||||
sg_cpu->cached_raw_freq = freq;
|
||||
return cpufreq_driver_resolve_freq(policy, freq);
|
||||
}
|
||||
|
||||
static void sugov_update_single(struct update_util_data *hook, u64 time,
|
||||
@@ -143,13 +156,14 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
|
||||
return;
|
||||
|
||||
next_f = util == ULONG_MAX ? policy->cpuinfo.max_freq :
|
||||
get_next_freq(policy, util, max);
|
||||
get_next_freq(sg_cpu, util, max);
|
||||
sugov_update_commit(sg_policy, time, next_f);
|
||||
}
|
||||
|
||||
static unsigned int sugov_next_freq_shared(struct sugov_policy *sg_policy,
|
||||
static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu,
|
||||
unsigned long util, unsigned long max)
|
||||
{
|
||||
struct sugov_policy *sg_policy = sg_cpu->sg_policy;
|
||||
struct cpufreq_policy *policy = sg_policy->policy;
|
||||
unsigned int max_f = policy->cpuinfo.max_freq;
|
||||
u64 last_freq_update_time = sg_policy->last_freq_update_time;
|
||||
@@ -189,7 +203,7 @@ static unsigned int sugov_next_freq_shared(struct sugov_policy *sg_policy,
|
||||
}
|
||||
}
|
||||
|
||||
return get_next_freq(policy, util, max);
|
||||
return get_next_freq(sg_cpu, util, max);
|
||||
}
|
||||
|
||||
static void sugov_update_shared(struct update_util_data *hook, u64 time,
|
||||
@@ -206,7 +220,7 @@ static void sugov_update_shared(struct update_util_data *hook, u64 time,
|
||||
sg_cpu->last_update = time;
|
||||
|
||||
if (sugov_should_update_freq(sg_policy, time)) {
|
||||
next_f = sugov_next_freq_shared(sg_policy, util, max);
|
||||
next_f = sugov_next_freq_shared(sg_cpu, util, max);
|
||||
sugov_update_commit(sg_policy, time, next_f);
|
||||
}
|
||||
|
||||
@@ -394,7 +408,7 @@ static int sugov_init(struct cpufreq_policy *policy)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sugov_exit(struct cpufreq_policy *policy)
|
||||
static void sugov_exit(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct sugov_policy *sg_policy = policy->governor_data;
|
||||
struct sugov_tunables *tunables = sg_policy->tunables;
|
||||
@@ -412,7 +426,6 @@ static int sugov_exit(struct cpufreq_policy *policy)
|
||||
mutex_unlock(&global_tunables_lock);
|
||||
|
||||
sugov_policy_free(sg_policy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sugov_start(struct cpufreq_policy *policy)
|
||||
@@ -434,6 +447,7 @@ static int sugov_start(struct cpufreq_policy *policy)
|
||||
sg_cpu->util = ULONG_MAX;
|
||||
sg_cpu->max = 0;
|
||||
sg_cpu->last_update = 0;
|
||||
sg_cpu->cached_raw_freq = 0;
|
||||
cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
|
||||
sugov_update_shared);
|
||||
} else {
|
||||
@@ -444,7 +458,7 @@ static int sugov_start(struct cpufreq_policy *policy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sugov_stop(struct cpufreq_policy *policy)
|
||||
static void sugov_stop(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct sugov_policy *sg_policy = policy->governor_data;
|
||||
unsigned int cpu;
|
||||
@@ -456,53 +470,29 @@ static int sugov_stop(struct cpufreq_policy *policy)
|
||||
|
||||
irq_work_sync(&sg_policy->irq_work);
|
||||
cancel_work_sync(&sg_policy->work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sugov_limits(struct cpufreq_policy *policy)
|
||||
static void sugov_limits(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct sugov_policy *sg_policy = policy->governor_data;
|
||||
|
||||
if (!policy->fast_switch_enabled) {
|
||||
mutex_lock(&sg_policy->work_lock);
|
||||
|
||||
if (policy->max < policy->cur)
|
||||
__cpufreq_driver_target(policy, policy->max,
|
||||
CPUFREQ_RELATION_H);
|
||||
else if (policy->min > policy->cur)
|
||||
__cpufreq_driver_target(policy, policy->min,
|
||||
CPUFREQ_RELATION_L);
|
||||
|
||||
cpufreq_policy_apply_limits(policy);
|
||||
mutex_unlock(&sg_policy->work_lock);
|
||||
}
|
||||
|
||||
sg_policy->need_freq_update = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sugov_governor(struct cpufreq_policy *policy, unsigned int event)
|
||||
{
|
||||
if (event == CPUFREQ_GOV_POLICY_INIT) {
|
||||
return sugov_init(policy);
|
||||
} else if (policy->governor_data) {
|
||||
switch (event) {
|
||||
case CPUFREQ_GOV_POLICY_EXIT:
|
||||
return sugov_exit(policy);
|
||||
case CPUFREQ_GOV_START:
|
||||
return sugov_start(policy);
|
||||
case CPUFREQ_GOV_STOP:
|
||||
return sugov_stop(policy);
|
||||
case CPUFREQ_GOV_LIMITS:
|
||||
return sugov_limits(policy);
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct cpufreq_governor schedutil_gov = {
|
||||
.name = "schedutil",
|
||||
.governor = sugov_governor,
|
||||
.owner = THIS_MODULE,
|
||||
.init = sugov_init,
|
||||
.exit = sugov_exit,
|
||||
.start = sugov_start,
|
||||
.stop = sugov_stop,
|
||||
.limits = sugov_limits,
|
||||
};
|
||||
|
||||
static int __init sugov_module_init(void)
|
||||
|
||||
Reference in New Issue
Block a user