aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-14 15:46:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-14 15:46:13 -0400
commitef98988ba369da88bab8a4d457407e71bbe160fa (patch)
treed421d3401aab6d4f654f85707c584bdf6fe3d0ec /drivers/cpufreq
parentf34d3606f76a8121b9d4940d2dd436bebeb2f9d7 (diff)
parent383731d98e768e15f4a8d69ae87957b933323ed7 (diff)
Merge tag 'pm-extra-4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull more power management updates from Rafael Wysocki: "This includes a couple of fixes for cpufreq regressions introduced in 4.8, a rework of the intel_pstate algorithm used on Atom processors (that took some time to test) plus a fix and a couple of cleanups in that driver, a CPPC cpufreq driver fix, and a some devfreq fixes and cleanups (core and exynos-nocp). Specifics: - Fix two cpufreq regressions causing undesirable changes in behavior to appear (one in the core and one in the conservative governor) introduced during the 4.8 cycle (Aaro Koskinen, Rafael Wysocki). - Fix the way the intel_pstate driver accesses MSRs related to the hardware-managed P-states (HWP) feature during the initialization which currently is unsafe and may cause the processor to generate a general protection fault (Srinivas Pandruvada). - Rework the intel_pstate's P-state selection algorithm used on Atom processors to avoid known problems with the current one and to make the computation more straightforward, which also happens to improve performance in multiple benchmarks a bit (Rafael Wysocki). - Improve two comments in the intel_pstate driver (Rafael Wysocki). - Fix the desired performance computation in the CPPC cpufreq driver (Hoan Tran). - Fix the devfreq core to avoid printing misleading error messages in some cases (Tobias Jakobi). - Fix the error code path in devfreq_add_device() to use proper locking around list modifications (Axel Lin). - Fix a build failure and remove a couple of redundant updates of variables in the exynos-nocp devfreq driver (Axel Lin)" * tag 'pm-extra-4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: 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 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 cpufreq: intel_pstate: Clarify comment in get_target_pstate_use_performance() cpufreq: intel_pstate: Fix unsafe HWP MSR access
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c8
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c19
-rw-r--r--drivers/cpufreq/intel_pstate.c43
3 files changed, 55 insertions, 15 deletions
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 1b2f28f69a81..4852d9efe74e 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -80,11 +80,17 @@ static int cppc_cpufreq_set_target(struct cpufreq_policy *policy,
80{ 80{
81 struct cppc_cpudata *cpu; 81 struct cppc_cpudata *cpu;
82 struct cpufreq_freqs freqs; 82 struct cpufreq_freqs freqs;
83 u32 desired_perf;
83 int ret = 0; 84 int ret = 0;
84 85
85 cpu = all_cpu_data[policy->cpu]; 86 cpu = all_cpu_data[policy->cpu];
86 87
87 cpu->perf_ctrls.desired_perf = (u64)target_freq * policy->max / cppc_dmi_max_khz; 88 desired_perf = (u64)target_freq * cpu->perf_caps.highest_perf / cppc_dmi_max_khz;
89 /* Return if it is exactly the same perf */
90 if (desired_perf == cpu->perf_ctrls.desired_perf)
91 return ret;
92
93 cpu->perf_ctrls.desired_perf = desired_perf;
88 freqs.old = policy->cur; 94 freqs.old = policy->cur;
89 freqs.new = target_freq; 95 freqs.new = target_freq;
90 96
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 18da4f8051d3..13475890d792 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -17,6 +17,7 @@
17struct cs_policy_dbs_info { 17struct cs_policy_dbs_info {
18 struct policy_dbs_info policy_dbs; 18 struct policy_dbs_info policy_dbs;
19 unsigned int down_skip; 19 unsigned int down_skip;
20 unsigned int requested_freq;
20}; 21};
21 22
22static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs) 23static 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)
61{ 62{
62 struct policy_dbs_info *policy_dbs = policy->governor_data; 63 struct policy_dbs_info *policy_dbs = policy->governor_data;
63 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs); 64 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
65 unsigned int requested_freq = dbs_info->requested_freq;
64 struct dbs_data *dbs_data = policy_dbs->dbs_data; 66 struct dbs_data *dbs_data = policy_dbs->dbs_data;
65 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 67 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
66 unsigned int load = dbs_update(policy); 68 unsigned int load = dbs_update(policy);
@@ -72,10 +74,16 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
72 if (cs_tuners->freq_step == 0) 74 if (cs_tuners->freq_step == 0)
73 goto out; 75 goto out;
74 76
77 /*
78 * If requested_freq is out of range, it is likely that the limits
79 * changed in the meantime, so fall back to current frequency in that
80 * case.
81 */
82 if (requested_freq > policy->max || requested_freq < policy->min)
83 requested_freq = policy->cur;
84
75 /* Check for frequency increase */ 85 /* Check for frequency increase */
76 if (load > dbs_data->up_threshold) { 86 if (load > dbs_data->up_threshold) {
77 unsigned int requested_freq = policy->cur;
78
79 dbs_info->down_skip = 0; 87 dbs_info->down_skip = 0;
80 88
81 /* if we are already at full speed then break out early */ 89 /* 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)
83 goto out; 91 goto out;
84 92
85 requested_freq += get_freq_target(cs_tuners, policy); 93 requested_freq += get_freq_target(cs_tuners, policy);
94 if (requested_freq > policy->max)
95 requested_freq = policy->max;
86 96
87 __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_H); 97 __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_H);
98 dbs_info->requested_freq = requested_freq;
88 goto out; 99 goto out;
89 } 100 }
90 101
@@ -95,7 +106,7 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
95 106
96 /* Check for frequency decrease */ 107 /* Check for frequency decrease */
97 if (load < cs_tuners->down_threshold) { 108 if (load < cs_tuners->down_threshold) {
98 unsigned int freq_target, requested_freq = policy->cur; 109 unsigned int freq_target;
99 /* 110 /*
100 * if we cannot reduce the frequency anymore, break out early 111 * if we cannot reduce the frequency anymore, break out early
101 */ 112 */
@@ -109,6 +120,7 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
109 requested_freq = policy->min; 120 requested_freq = policy->min;
110 121
111 __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_L); 122 __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_L);
123 dbs_info->requested_freq = requested_freq;
112 } 124 }
113 125
114 out: 126 out:
@@ -287,6 +299,7 @@ static void cs_start(struct cpufreq_policy *policy)
287 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data); 299 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
288 300
289 dbs_info->down_skip = 0; 301 dbs_info->down_skip = 0;
302 dbs_info->requested_freq = policy->cur;
290} 303}
291 304
292static struct dbs_governor cs_governor = { 305static struct dbs_governor cs_governor = {
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 806f2039571e..f535f8123258 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -225,7 +225,7 @@ struct cpudata {
225static struct cpudata **all_cpu_data; 225static struct cpudata **all_cpu_data;
226 226
227/** 227/**
228 * struct pid_adjust_policy - Stores static PID configuration data 228 * struct pstate_adjust_policy - Stores static PID configuration data
229 * @sample_rate_ms: PID calculation sample rate in ms 229 * @sample_rate_ms: PID calculation sample rate in ms
230 * @sample_rate_ns: Sample rate calculation in ns 230 * @sample_rate_ns: Sample rate calculation in ns
231 * @deadband: PID deadband 231 * @deadband: PID deadband
@@ -562,12 +562,12 @@ static void intel_pstate_hwp_set(const struct cpumask *cpumask)
562 int min, hw_min, max, hw_max, cpu, range, adj_range; 562 int min, hw_min, max, hw_max, cpu, range, adj_range;
563 u64 value, cap; 563 u64 value, cap;
564 564
565 rdmsrl(MSR_HWP_CAPABILITIES, cap);
566 hw_min = HWP_LOWEST_PERF(cap);
567 hw_max = HWP_HIGHEST_PERF(cap);
568 range = hw_max - hw_min;
569
570 for_each_cpu(cpu, cpumask) { 565 for_each_cpu(cpu, cpumask) {
566 rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap);
567 hw_min = HWP_LOWEST_PERF(cap);
568 hw_max = HWP_HIGHEST_PERF(cap);
569 range = hw_max - hw_min;
570
571 rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value); 571 rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value);
572 adj_range = limits->min_perf_pct * range / 100; 572 adj_range = limits->min_perf_pct * range / 100;
573 min = hw_min + adj_range; 573 min = hw_min + adj_range;
@@ -1232,6 +1232,7 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
1232{ 1232{
1233 struct sample *sample = &cpu->sample; 1233 struct sample *sample = &cpu->sample;
1234 int32_t busy_frac, boost; 1234 int32_t busy_frac, boost;
1235 int target, avg_pstate;
1235 1236
1236 busy_frac = div_fp(sample->mperf, sample->tsc); 1237 busy_frac = div_fp(sample->mperf, sample->tsc);
1237 1238
@@ -1242,7 +1243,26 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
1242 busy_frac = boost; 1243 busy_frac = boost;
1243 1244
1244 sample->busy_scaled = busy_frac * 100; 1245 sample->busy_scaled = busy_frac * 100;
1245 return get_avg_pstate(cpu) - pid_calc(&cpu->pid, sample->busy_scaled); 1246
1247 target = limits->no_turbo || limits->turbo_disabled ?
1248 cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
1249 target += target >> 2;
1250 target = mul_fp(target, busy_frac);
1251 if (target < cpu->pstate.min_pstate)
1252 target = cpu->pstate.min_pstate;
1253
1254 /*
1255 * If the average P-state during the previous cycle was higher than the
1256 * current target, add 50% of the difference to the target to reduce
1257 * possible performance oscillations and offset possible performance
1258 * loss related to moving the workload from one CPU to another within
1259 * a package/module.
1260 */
1261 avg_pstate = get_avg_pstate(cpu);
1262 if (avg_pstate > target)
1263 target += (avg_pstate - target) >> 1;
1264
1265 return target;
1246} 1266}
1247 1267
1248static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu) 1268static 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)
1251 u64 duration_ns; 1271 u64 duration_ns;
1252 1272
1253 /* 1273 /*
1254 * perf_scaled is the average performance during the last sampling 1274 * perf_scaled is the ratio of the average P-state during the last
1255 * period scaled by the ratio of the maximum P-state to the P-state 1275 * sampling period to the P-state requested last time (in percent).
1256 * requested last time (in percent). That measures the system's 1276 *
1257 * response to the previous P-state selection. 1277 * That measures the system's response to the previous P-state
1278 * selection.
1258 */ 1279 */
1259 max_pstate = cpu->pstate.max_pstate_physical; 1280 max_pstate = cpu->pstate.max_pstate_physical;
1260 current_pstate = cpu->pstate.current_pstate; 1281 current_pstate = cpu->pstate.current_pstate;