diff options
author | Gabriele Mazzotta <gabriele.mzt@gmail.com> | 2014-10-13 11:37:41 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-10-23 16:59:59 -0400 |
commit | 4521e1a0ce173daa23dfef8312d09051e057ff8e (patch) | |
tree | 50e75a75204f297d8867c5e8e6ec00ee8fb6deca /drivers/cpufreq | |
parent | c034b02e213d271b98c45c4a7b54af8f69aaac1e (diff) |
cpufreq: intel_pstate: Reflect current no_turbo state correctly
Some BIOSes modify the state of MSR_IA32_MISC_ENABLE_TURBO_DISABLE
based on the current power source for the system battery AC vs
battery. Reflect the correct current state and ability to modify the
no_turbo sysfs file based on current state of
MSR_IA32_MISC_ENABLE_TURBO_DISABLE.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=83151
Cc: All applicable <stable@vger.kernel.org>
Signed-off-by: Gabriele Mazzotta <gabriele.mzt@gmail.com>
Signed-off-by: Dirk Brandewie <dirk.j.brandewie@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 7547ab559a97..5f5f5ed11691 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -138,6 +138,7 @@ struct perf_limits { | |||
138 | 138 | ||
139 | static struct perf_limits limits = { | 139 | static struct perf_limits limits = { |
140 | .no_turbo = 0, | 140 | .no_turbo = 0, |
141 | .turbo_disabled = 0, | ||
141 | .max_perf_pct = 100, | 142 | .max_perf_pct = 100, |
142 | .max_perf = int_tofp(1), | 143 | .max_perf = int_tofp(1), |
143 | .min_perf_pct = 0, | 144 | .min_perf_pct = 0, |
@@ -218,6 +219,18 @@ static inline void intel_pstate_reset_all_pid(void) | |||
218 | } | 219 | } |
219 | } | 220 | } |
220 | 221 | ||
222 | static inline void update_turbo_state(void) | ||
223 | { | ||
224 | u64 misc_en; | ||
225 | struct cpudata *cpu; | ||
226 | |||
227 | cpu = all_cpu_data[0]; | ||
228 | rdmsrl(MSR_IA32_MISC_ENABLE, misc_en); | ||
229 | limits.turbo_disabled = | ||
230 | (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE || | ||
231 | cpu->pstate.max_pstate == cpu->pstate.turbo_pstate); | ||
232 | } | ||
233 | |||
221 | /************************** debugfs begin ************************/ | 234 | /************************** debugfs begin ************************/ |
222 | static int pid_param_set(void *data, u64 val) | 235 | static int pid_param_set(void *data, u64 val) |
223 | { | 236 | { |
@@ -274,6 +287,20 @@ static void __init intel_pstate_debug_expose_params(void) | |||
274 | return sprintf(buf, "%u\n", limits.object); \ | 287 | return sprintf(buf, "%u\n", limits.object); \ |
275 | } | 288 | } |
276 | 289 | ||
290 | static ssize_t show_no_turbo(struct kobject *kobj, | ||
291 | struct attribute *attr, char *buf) | ||
292 | { | ||
293 | ssize_t ret; | ||
294 | |||
295 | update_turbo_state(); | ||
296 | if (limits.turbo_disabled) | ||
297 | ret = sprintf(buf, "%u\n", limits.turbo_disabled); | ||
298 | else | ||
299 | ret = sprintf(buf, "%u\n", limits.no_turbo); | ||
300 | |||
301 | return ret; | ||
302 | } | ||
303 | |||
277 | static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, | 304 | static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, |
278 | const char *buf, size_t count) | 305 | const char *buf, size_t count) |
279 | { | 306 | { |
@@ -283,11 +310,14 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, | |||
283 | ret = sscanf(buf, "%u", &input); | 310 | ret = sscanf(buf, "%u", &input); |
284 | if (ret != 1) | 311 | if (ret != 1) |
285 | return -EINVAL; | 312 | return -EINVAL; |
286 | limits.no_turbo = clamp_t(int, input, 0 , 1); | 313 | |
314 | update_turbo_state(); | ||
287 | if (limits.turbo_disabled) { | 315 | if (limits.turbo_disabled) { |
288 | pr_warn("Turbo disabled by BIOS or unavailable on processor\n"); | 316 | pr_warn("Turbo disabled by BIOS or unavailable on processor\n"); |
289 | limits.no_turbo = limits.turbo_disabled; | 317 | return -EPERM; |
290 | } | 318 | } |
319 | limits.no_turbo = clamp_t(int, input, 0, 1); | ||
320 | |||
291 | return count; | 321 | return count; |
292 | } | 322 | } |
293 | 323 | ||
@@ -323,7 +353,6 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, | |||
323 | return count; | 353 | return count; |
324 | } | 354 | } |
325 | 355 | ||
326 | show_one(no_turbo, no_turbo); | ||
327 | show_one(max_perf_pct, max_perf_pct); | 356 | show_one(max_perf_pct, max_perf_pct); |
328 | show_one(min_perf_pct, min_perf_pct); | 357 | show_one(min_perf_pct, min_perf_pct); |
329 | 358 | ||
@@ -501,7 +530,7 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) | |||
501 | int max_perf_adj; | 530 | int max_perf_adj; |
502 | int min_perf; | 531 | int min_perf; |
503 | 532 | ||
504 | if (limits.no_turbo) | 533 | if (limits.no_turbo || limits.turbo_disabled) |
505 | max_perf = cpu->pstate.max_pstate; | 534 | max_perf = cpu->pstate.max_pstate; |
506 | 535 | ||
507 | max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf)); | 536 | max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf)); |
@@ -516,6 +545,8 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) | |||
516 | { | 545 | { |
517 | int max_perf, min_perf; | 546 | int max_perf, min_perf; |
518 | 547 | ||
548 | update_turbo_state(); | ||
549 | |||
519 | intel_pstate_get_min_max(cpu, &min_perf, &max_perf); | 550 | intel_pstate_get_min_max(cpu, &min_perf, &max_perf); |
520 | 551 | ||
521 | pstate = clamp_t(int, pstate, min_perf, max_perf); | 552 | pstate = clamp_t(int, pstate, min_perf, max_perf); |
@@ -717,7 +748,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
717 | limits.max_policy_pct = 100; | 748 | limits.max_policy_pct = 100; |
718 | limits.max_perf_pct = 100; | 749 | limits.max_perf_pct = 100; |
719 | limits.max_perf = int_tofp(1); | 750 | limits.max_perf = int_tofp(1); |
720 | limits.no_turbo = limits.turbo_disabled; | 751 | limits.no_turbo = 0; |
721 | return 0; | 752 | return 0; |
722 | } | 753 | } |
723 | limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; | 754 | limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; |
@@ -760,7 +791,6 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) | |||
760 | { | 791 | { |
761 | struct cpudata *cpu; | 792 | struct cpudata *cpu; |
762 | int rc; | 793 | int rc; |
763 | u64 misc_en; | ||
764 | 794 | ||
765 | rc = intel_pstate_init_cpu(policy->cpu); | 795 | rc = intel_pstate_init_cpu(policy->cpu); |
766 | if (rc) | 796 | if (rc) |
@@ -768,12 +798,6 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) | |||
768 | 798 | ||
769 | cpu = all_cpu_data[policy->cpu]; | 799 | cpu = all_cpu_data[policy->cpu]; |
770 | 800 | ||
771 | rdmsrl(MSR_IA32_MISC_ENABLE, misc_en); | ||
772 | if (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE || | ||
773 | cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) { | ||
774 | limits.turbo_disabled = 1; | ||
775 | limits.no_turbo = 1; | ||
776 | } | ||
777 | if (limits.min_perf_pct == 100 && limits.max_perf_pct == 100) | 801 | if (limits.min_perf_pct == 100 && limits.max_perf_pct == 100) |
778 | policy->policy = CPUFREQ_POLICY_PERFORMANCE; | 802 | policy->policy = CPUFREQ_POLICY_PERFORMANCE; |
779 | else | 803 | else |