diff options
Diffstat (limited to 'drivers/cpufreq/intel_pstate.c')
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index cddc61939a86..3af9dd7332e6 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -260,24 +260,31 @@ static inline void update_turbo_state(void) | |||
260 | cpu->pstate.max_pstate == cpu->pstate.turbo_pstate); | 260 | cpu->pstate.max_pstate == cpu->pstate.turbo_pstate); |
261 | } | 261 | } |
262 | 262 | ||
263 | #define PCT_TO_HWP(x) (x * 255 / 100) | ||
264 | static void intel_pstate_hwp_set(void) | 263 | static void intel_pstate_hwp_set(void) |
265 | { | 264 | { |
266 | int min, max, cpu; | 265 | int min, hw_min, max, hw_max, cpu, range, adj_range; |
267 | u64 value, freq; | 266 | u64 value, cap; |
267 | |||
268 | rdmsrl(MSR_HWP_CAPABILITIES, cap); | ||
269 | hw_min = HWP_LOWEST_PERF(cap); | ||
270 | hw_max = HWP_HIGHEST_PERF(cap); | ||
271 | range = hw_max - hw_min; | ||
268 | 272 | ||
269 | get_online_cpus(); | 273 | get_online_cpus(); |
270 | 274 | ||
271 | for_each_online_cpu(cpu) { | 275 | for_each_online_cpu(cpu) { |
272 | rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value); | 276 | rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value); |
273 | min = PCT_TO_HWP(limits.min_perf_pct); | 277 | adj_range = limits.min_perf_pct * range / 100; |
278 | min = hw_min + adj_range; | ||
274 | value &= ~HWP_MIN_PERF(~0L); | 279 | value &= ~HWP_MIN_PERF(~0L); |
275 | value |= HWP_MIN_PERF(min); | 280 | value |= HWP_MIN_PERF(min); |
276 | 281 | ||
277 | max = PCT_TO_HWP(limits.max_perf_pct); | 282 | adj_range = limits.max_perf_pct * range / 100; |
283 | max = hw_min + adj_range; | ||
278 | if (limits.no_turbo) { | 284 | if (limits.no_turbo) { |
279 | rdmsrl( MSR_HWP_CAPABILITIES, freq); | 285 | hw_max = HWP_GUARANTEED_PERF(cap); |
280 | max = HWP_GUARANTEED_PERF(freq); | 286 | if (hw_max < max) |
287 | max = hw_max; | ||
281 | } | 288 | } |
282 | 289 | ||
283 | value &= ~HWP_MAX_PERF(~0L); | 290 | value &= ~HWP_MAX_PERF(~0L); |
@@ -423,6 +430,8 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b, | |||
423 | 430 | ||
424 | limits.max_sysfs_pct = clamp_t(int, input, 0 , 100); | 431 | limits.max_sysfs_pct = clamp_t(int, input, 0 , 100); |
425 | limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct); | 432 | limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct); |
433 | limits.max_perf_pct = max(limits.min_policy_pct, limits.max_perf_pct); | ||
434 | limits.max_perf_pct = max(limits.min_perf_pct, limits.max_perf_pct); | ||
426 | limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); | 435 | limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); |
427 | 436 | ||
428 | if (hwp_active) | 437 | if (hwp_active) |
@@ -442,6 +451,8 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, | |||
442 | 451 | ||
443 | limits.min_sysfs_pct = clamp_t(int, input, 0 , 100); | 452 | limits.min_sysfs_pct = clamp_t(int, input, 0 , 100); |
444 | limits.min_perf_pct = max(limits.min_policy_pct, limits.min_sysfs_pct); | 453 | limits.min_perf_pct = max(limits.min_policy_pct, limits.min_sysfs_pct); |
454 | limits.min_perf_pct = min(limits.max_policy_pct, limits.min_perf_pct); | ||
455 | limits.min_perf_pct = min(limits.max_perf_pct, limits.min_perf_pct); | ||
445 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); | 456 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); |
446 | 457 | ||
447 | if (hwp_active) | 458 | if (hwp_active) |
@@ -989,12 +1000,19 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
989 | 1000 | ||
990 | limits.min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq; | 1001 | limits.min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq; |
991 | limits.min_policy_pct = clamp_t(int, limits.min_policy_pct, 0 , 100); | 1002 | limits.min_policy_pct = clamp_t(int, limits.min_policy_pct, 0 , 100); |
992 | limits.min_perf_pct = max(limits.min_policy_pct, limits.min_sysfs_pct); | ||
993 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); | ||
994 | |||
995 | limits.max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq; | 1003 | limits.max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq; |
996 | limits.max_policy_pct = clamp_t(int, limits.max_policy_pct, 0 , 100); | 1004 | limits.max_policy_pct = clamp_t(int, limits.max_policy_pct, 0 , 100); |
1005 | |||
1006 | /* Normalize user input to [min_policy_pct, max_policy_pct] */ | ||
1007 | limits.min_perf_pct = max(limits.min_policy_pct, limits.min_sysfs_pct); | ||
1008 | limits.min_perf_pct = min(limits.max_policy_pct, limits.min_perf_pct); | ||
997 | limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct); | 1009 | limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct); |
1010 | limits.max_perf_pct = max(limits.min_policy_pct, limits.max_perf_pct); | ||
1011 | |||
1012 | /* Make sure min_perf_pct <= max_perf_pct */ | ||
1013 | limits.min_perf_pct = min(limits.max_perf_pct, limits.min_perf_pct); | ||
1014 | |||
1015 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); | ||
998 | limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); | 1016 | limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); |
999 | 1017 | ||
1000 | if (hwp_active) | 1018 | if (hwp_active) |