Merge branches 'pm-cpufreq' and 'pm-devfreq'
* pm-cpufreq: cpufreq: CPPC: Correct desired_perf calculation cpufreq: conservative: Fix next frequency selection cpufreq: skip invalid entries when searching the frequency cpufreq: intel_pstate: Fix struct pstate_adjust_policy kerneldoc cpufreq: intel_pstate: Proportional algorithm for Atom cpufreq: intel_pstate: Clarify comment in get_target_pstate_use_performance() cpufreq: intel_pstate: Fix unsafe HWP MSR access * pm-devfreq: PM / devfreq: Skip status update on uninitialized previous_freq PM / devfreq: Add proper locking around list_del() PM / devfreq: exynos-nocp: Remove redundant code PM / devfreq: exynos-nocp: Select REGMAP_MMIO
This commit is contained in:
Коммит
383731d98e
|
@ -80,11 +80,17 @@ static int cppc_cpufreq_set_target(struct cpufreq_policy *policy,
|
|||
{
|
||||
struct cpudata *cpu;
|
||||
struct cpufreq_freqs freqs;
|
||||
u32 desired_perf;
|
||||
int ret = 0;
|
||||
|
||||
cpu = all_cpu_data[policy->cpu];
|
||||
|
||||
cpu->perf_ctrls.desired_perf = (u64)target_freq * policy->max / cppc_dmi_max_khz;
|
||||
desired_perf = (u64)target_freq * cpu->perf_caps.highest_perf / cppc_dmi_max_khz;
|
||||
/* Return if it is exactly the same perf */
|
||||
if (desired_perf == cpu->perf_ctrls.desired_perf)
|
||||
return ret;
|
||||
|
||||
cpu->perf_ctrls.desired_perf = desired_perf;
|
||||
freqs.old = policy->cur;
|
||||
freqs.new = target_freq;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
struct cs_policy_dbs_info {
|
||||
struct policy_dbs_info policy_dbs;
|
||||
unsigned int down_skip;
|
||||
unsigned int requested_freq;
|
||||
};
|
||||
|
||||
static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs)
|
||||
|
@ -61,6 +62,7 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
|
|||
{
|
||||
struct policy_dbs_info *policy_dbs = policy->governor_data;
|
||||
struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
|
||||
unsigned int requested_freq = dbs_info->requested_freq;
|
||||
struct dbs_data *dbs_data = policy_dbs->dbs_data;
|
||||
struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
|
||||
unsigned int load = dbs_update(policy);
|
||||
|
@ -72,10 +74,16 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
|
|||
if (cs_tuners->freq_step == 0)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* If requested_freq is out of range, it is likely that the limits
|
||||
* changed in the meantime, so fall back to current frequency in that
|
||||
* case.
|
||||
*/
|
||||
if (requested_freq > policy->max || requested_freq < policy->min)
|
||||
requested_freq = policy->cur;
|
||||
|
||||
/* Check for frequency increase */
|
||||
if (load > dbs_data->up_threshold) {
|
||||
unsigned int requested_freq = policy->cur;
|
||||
|
||||
dbs_info->down_skip = 0;
|
||||
|
||||
/* if we are already at full speed then break out early */
|
||||
|
@ -83,8 +91,11 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
|
|||
goto out;
|
||||
|
||||
requested_freq += get_freq_target(cs_tuners, policy);
|
||||
if (requested_freq > policy->max)
|
||||
requested_freq = policy->max;
|
||||
|
||||
__cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_H);
|
||||
dbs_info->requested_freq = requested_freq;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -95,7 +106,7 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
|
|||
|
||||
/* Check for frequency decrease */
|
||||
if (load < cs_tuners->down_threshold) {
|
||||
unsigned int freq_target, requested_freq = policy->cur;
|
||||
unsigned int freq_target;
|
||||
/*
|
||||
* if we cannot reduce the frequency anymore, break out early
|
||||
*/
|
||||
|
@ -109,6 +120,7 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
|
|||
requested_freq = policy->min;
|
||||
|
||||
__cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_L);
|
||||
dbs_info->requested_freq = requested_freq;
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -287,6 +299,7 @@ static void cs_start(struct cpufreq_policy *policy)
|
|||
struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
|
||||
|
||||
dbs_info->down_skip = 0;
|
||||
dbs_info->requested_freq = policy->cur;
|
||||
}
|
||||
|
||||
static struct dbs_governor cs_governor = {
|
||||
|
|
|
@ -225,7 +225,7 @@ struct cpudata {
|
|||
static struct cpudata **all_cpu_data;
|
||||
|
||||
/**
|
||||
* struct pid_adjust_policy - Stores static PID configuration data
|
||||
* struct pstate_adjust_policy - Stores static PID configuration data
|
||||
* @sample_rate_ms: PID calculation sample rate in ms
|
||||
* @sample_rate_ns: Sample rate calculation in ns
|
||||
* @deadband: PID deadband
|
||||
|
@ -562,12 +562,12 @@ static void intel_pstate_hwp_set(const struct cpumask *cpumask)
|
|||
int min, hw_min, max, hw_max, cpu, range, adj_range;
|
||||
u64 value, cap;
|
||||
|
||||
rdmsrl(MSR_HWP_CAPABILITIES, cap);
|
||||
hw_min = HWP_LOWEST_PERF(cap);
|
||||
hw_max = HWP_HIGHEST_PERF(cap);
|
||||
range = hw_max - hw_min;
|
||||
|
||||
for_each_cpu(cpu, cpumask) {
|
||||
rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap);
|
||||
hw_min = HWP_LOWEST_PERF(cap);
|
||||
hw_max = HWP_HIGHEST_PERF(cap);
|
||||
range = hw_max - hw_min;
|
||||
|
||||
rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value);
|
||||
adj_range = limits->min_perf_pct * range / 100;
|
||||
min = hw_min + adj_range;
|
||||
|
@ -1232,6 +1232,7 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
|
|||
{
|
||||
struct sample *sample = &cpu->sample;
|
||||
int32_t busy_frac, boost;
|
||||
int target, avg_pstate;
|
||||
|
||||
busy_frac = div_fp(sample->mperf, sample->tsc);
|
||||
|
||||
|
@ -1242,7 +1243,26 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
|
|||
busy_frac = boost;
|
||||
|
||||
sample->busy_scaled = busy_frac * 100;
|
||||
return get_avg_pstate(cpu) - pid_calc(&cpu->pid, sample->busy_scaled);
|
||||
|
||||
target = limits->no_turbo || limits->turbo_disabled ?
|
||||
cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
|
||||
target += target >> 2;
|
||||
target = mul_fp(target, busy_frac);
|
||||
if (target < cpu->pstate.min_pstate)
|
||||
target = cpu->pstate.min_pstate;
|
||||
|
||||
/*
|
||||
* If the average P-state during the previous cycle was higher than the
|
||||
* current target, add 50% of the difference to the target to reduce
|
||||
* possible performance oscillations and offset possible performance
|
||||
* loss related to moving the workload from one CPU to another within
|
||||
* a package/module.
|
||||
*/
|
||||
avg_pstate = get_avg_pstate(cpu);
|
||||
if (avg_pstate > target)
|
||||
target += (avg_pstate - target) >> 1;
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
|
||||
|
@ -1251,10 +1271,11 @@ static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
|
|||
u64 duration_ns;
|
||||
|
||||
/*
|
||||
* perf_scaled is the average performance during the last sampling
|
||||
* period scaled by the ratio of the maximum P-state to the P-state
|
||||
* requested last time (in percent). That measures the system's
|
||||
* response to the previous P-state selection.
|
||||
* perf_scaled is the ratio of the average P-state during the last
|
||||
* sampling period to the P-state requested last time (in percent).
|
||||
*
|
||||
* That measures the system's response to the previous P-state
|
||||
* selection.
|
||||
*/
|
||||
max_pstate = cpu->pstate.max_pstate_physical;
|
||||
current_pstate = cpu->pstate.current_pstate;
|
||||
|
|
|
@ -137,6 +137,10 @@ static int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
|
|||
|
||||
cur_time = jiffies;
|
||||
|
||||
/* Immediately exit if previous_freq is not initialized yet. */
|
||||
if (!devfreq->previous_freq)
|
||||
goto out;
|
||||
|
||||
prev_lev = devfreq_get_freq_level(devfreq, devfreq->previous_freq);
|
||||
if (prev_lev < 0) {
|
||||
ret = prev_lev;
|
||||
|
@ -594,17 +598,19 @@ struct devfreq *devfreq_add_device(struct device *dev,
|
|||
if (devfreq->governor)
|
||||
err = devfreq->governor->event_handler(devfreq,
|
||||
DEVFREQ_GOV_START, NULL);
|
||||
mutex_unlock(&devfreq_list_lock);
|
||||
if (err) {
|
||||
dev_err(dev, "%s: Unable to start governor for the device\n",
|
||||
__func__);
|
||||
goto err_init;
|
||||
}
|
||||
mutex_unlock(&devfreq_list_lock);
|
||||
|
||||
return devfreq;
|
||||
|
||||
err_init:
|
||||
list_del(&devfreq->node);
|
||||
mutex_unlock(&devfreq_list_lock);
|
||||
|
||||
device_unregister(&devfreq->dev);
|
||||
err_out:
|
||||
return ERR_PTR(err);
|
||||
|
|
|
@ -17,6 +17,7 @@ config DEVFREQ_EVENT_EXYNOS_NOCP
|
|||
tristate "EXYNOS NoC (Network On Chip) Probe DEVFREQ event Driver"
|
||||
depends on ARCH_EXYNOS || COMPILE_TEST
|
||||
select PM_OPP
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
This add the devfreq-event driver for Exynos SoC. It provides NoC
|
||||
(Network on Chip) Probe counters to measure the bandwidth of AXI bus.
|
||||
|
|
|
@ -176,9 +176,6 @@ static int exynos_nocp_get_event(struct devfreq_event_dev *edev,
|
|||
return 0;
|
||||
|
||||
out:
|
||||
edata->load_count = 0;
|
||||
edata->total_count = 0;
|
||||
|
||||
dev_err(nocp->dev, "Failed to read the counter of NoC probe device\n");
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -639,19 +639,19 @@ static inline int cpufreq_table_find_index_al(struct cpufreq_policy *policy,
|
|||
unsigned int target_freq)
|
||||
{
|
||||
struct cpufreq_frequency_table *table = policy->freq_table;
|
||||
struct cpufreq_frequency_table *pos, *best = table - 1;
|
||||
unsigned int freq;
|
||||
int i, best = -1;
|
||||
|
||||
for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
freq = table[i].frequency;
|
||||
cpufreq_for_each_valid_entry(pos, table) {
|
||||
freq = pos->frequency;
|
||||
|
||||
if (freq >= target_freq)
|
||||
return i;
|
||||
return pos - table;
|
||||
|
||||
best = i;
|
||||
best = pos;
|
||||
}
|
||||
|
||||
return best;
|
||||
return best - table;
|
||||
}
|
||||
|
||||
/* Find lowest freq at or above target in a table in descending order */
|
||||
|
@ -659,28 +659,28 @@ static inline int cpufreq_table_find_index_dl(struct cpufreq_policy *policy,
|
|||
unsigned int target_freq)
|
||||
{
|
||||
struct cpufreq_frequency_table *table = policy->freq_table;
|
||||
struct cpufreq_frequency_table *pos, *best = table - 1;
|
||||
unsigned int freq;
|
||||
int i, best = -1;
|
||||
|
||||
for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
freq = table[i].frequency;
|
||||
cpufreq_for_each_valid_entry(pos, table) {
|
||||
freq = pos->frequency;
|
||||
|
||||
if (freq == target_freq)
|
||||
return i;
|
||||
return pos - table;
|
||||
|
||||
if (freq > target_freq) {
|
||||
best = i;
|
||||
best = pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No freq found above target_freq */
|
||||
if (best == -1)
|
||||
return i;
|
||||
if (best == table - 1)
|
||||
return pos - table;
|
||||
|
||||
return best;
|
||||
return best - pos;
|
||||
}
|
||||
|
||||
return best;
|
||||
return best - pos;
|
||||
}
|
||||
|
||||
/* Works only on sorted freq-tables */
|
||||
|
@ -700,28 +700,28 @@ static inline int cpufreq_table_find_index_ah(struct cpufreq_policy *policy,
|
|||
unsigned int target_freq)
|
||||
{
|
||||
struct cpufreq_frequency_table *table = policy->freq_table;
|
||||
struct cpufreq_frequency_table *pos, *best = table - 1;
|
||||
unsigned int freq;
|
||||
int i, best = -1;
|
||||
|
||||
for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
freq = table[i].frequency;
|
||||
cpufreq_for_each_valid_entry(pos, table) {
|
||||
freq = pos->frequency;
|
||||
|
||||
if (freq == target_freq)
|
||||
return i;
|
||||
return pos - table;
|
||||
|
||||
if (freq < target_freq) {
|
||||
best = i;
|
||||
best = pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No freq found below target_freq */
|
||||
if (best == -1)
|
||||
return i;
|
||||
if (best == table - 1)
|
||||
return pos - table;
|
||||
|
||||
return best;
|
||||
return best - table;
|
||||
}
|
||||
|
||||
return best;
|
||||
return best - table;
|
||||
}
|
||||
|
||||
/* Find highest freq at or below target in a table in descending order */
|
||||
|
@ -729,19 +729,19 @@ static inline int cpufreq_table_find_index_dh(struct cpufreq_policy *policy,
|
|||
unsigned int target_freq)
|
||||
{
|
||||
struct cpufreq_frequency_table *table = policy->freq_table;
|
||||
struct cpufreq_frequency_table *pos, *best = table - 1;
|
||||
unsigned int freq;
|
||||
int i, best = -1;
|
||||
|
||||
for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
freq = table[i].frequency;
|
||||
cpufreq_for_each_valid_entry(pos, table) {
|
||||
freq = pos->frequency;
|
||||
|
||||
if (freq <= target_freq)
|
||||
return i;
|
||||
return pos - table;
|
||||
|
||||
best = i;
|
||||
best = pos;
|
||||
}
|
||||
|
||||
return best;
|
||||
return best - table;
|
||||
}
|
||||
|
||||
/* Works only on sorted freq-tables */
|
||||
|
@ -761,32 +761,32 @@ static inline int cpufreq_table_find_index_ac(struct cpufreq_policy *policy,
|
|||
unsigned int target_freq)
|
||||
{
|
||||
struct cpufreq_frequency_table *table = policy->freq_table;
|
||||
struct cpufreq_frequency_table *pos, *best = table - 1;
|
||||
unsigned int freq;
|
||||
int i, best = -1;
|
||||
|
||||
for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
freq = table[i].frequency;
|
||||
cpufreq_for_each_valid_entry(pos, table) {
|
||||
freq = pos->frequency;
|
||||
|
||||
if (freq == target_freq)
|
||||
return i;
|
||||
return pos - table;
|
||||
|
||||
if (freq < target_freq) {
|
||||
best = i;
|
||||
best = pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No freq found below target_freq */
|
||||
if (best == -1)
|
||||
return i;
|
||||
if (best == table - 1)
|
||||
return pos - table;
|
||||
|
||||
/* Choose the closest freq */
|
||||
if (target_freq - table[best].frequency > freq - target_freq)
|
||||
return i;
|
||||
if (target_freq - best->frequency > freq - target_freq)
|
||||
return pos - table;
|
||||
|
||||
return best;
|
||||
return best - table;
|
||||
}
|
||||
|
||||
return best;
|
||||
return best - table;
|
||||
}
|
||||
|
||||
/* Find closest freq to target in a table in descending order */
|
||||
|
@ -794,32 +794,32 @@ static inline int cpufreq_table_find_index_dc(struct cpufreq_policy *policy,
|
|||
unsigned int target_freq)
|
||||
{
|
||||
struct cpufreq_frequency_table *table = policy->freq_table;
|
||||
struct cpufreq_frequency_table *pos, *best = table - 1;
|
||||
unsigned int freq;
|
||||
int i, best = -1;
|
||||
|
||||
for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
freq = table[i].frequency;
|
||||
cpufreq_for_each_valid_entry(pos, table) {
|
||||
freq = pos->frequency;
|
||||
|
||||
if (freq == target_freq)
|
||||
return i;
|
||||
return pos - table;
|
||||
|
||||
if (freq > target_freq) {
|
||||
best = i;
|
||||
best = pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No freq found above target_freq */
|
||||
if (best == -1)
|
||||
return i;
|
||||
if (best == table - 1)
|
||||
return pos - table;
|
||||
|
||||
/* Choose the closest freq */
|
||||
if (table[best].frequency - target_freq > target_freq - freq)
|
||||
return i;
|
||||
if (best->frequency - target_freq > target_freq - freq)
|
||||
return pos - table;
|
||||
|
||||
return best;
|
||||
return best - table;
|
||||
}
|
||||
|
||||
return best;
|
||||
return best - table;
|
||||
}
|
||||
|
||||
/* Works only on sorted freq-tables */
|
||||
|
|
Загрузка…
Ссылка в новой задаче