diff options
Diffstat (limited to 'drivers/cpufreq/intel_pstate.c')
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 742eefba12c2..872c5772c5d3 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -148,6 +148,8 @@ struct perf_limits { | |||
148 | int32_t min_perf; | 148 | int32_t min_perf; |
149 | int max_policy_pct; | 149 | int max_policy_pct; |
150 | int max_sysfs_pct; | 150 | int max_sysfs_pct; |
151 | int min_policy_pct; | ||
152 | int min_sysfs_pct; | ||
151 | }; | 153 | }; |
152 | 154 | ||
153 | static struct perf_limits limits = { | 155 | static struct perf_limits limits = { |
@@ -159,6 +161,8 @@ static struct perf_limits limits = { | |||
159 | .min_perf = 0, | 161 | .min_perf = 0, |
160 | .max_policy_pct = 100, | 162 | .max_policy_pct = 100, |
161 | .max_sysfs_pct = 100, | 163 | .max_sysfs_pct = 100, |
164 | .min_policy_pct = 0, | ||
165 | .min_sysfs_pct = 0, | ||
162 | }; | 166 | }; |
163 | 167 | ||
164 | static inline void pid_reset(struct _pid *pid, int setpoint, int busy, | 168 | static inline void pid_reset(struct _pid *pid, int setpoint, int busy, |
@@ -338,6 +342,33 @@ static void __init intel_pstate_debug_expose_params(void) | |||
338 | return sprintf(buf, "%u\n", limits.object); \ | 342 | return sprintf(buf, "%u\n", limits.object); \ |
339 | } | 343 | } |
340 | 344 | ||
345 | static ssize_t show_turbo_pct(struct kobject *kobj, | ||
346 | struct attribute *attr, char *buf) | ||
347 | { | ||
348 | struct cpudata *cpu; | ||
349 | int total, no_turbo, turbo_pct; | ||
350 | uint32_t turbo_fp; | ||
351 | |||
352 | cpu = all_cpu_data[0]; | ||
353 | |||
354 | total = cpu->pstate.turbo_pstate - cpu->pstate.min_pstate + 1; | ||
355 | no_turbo = cpu->pstate.max_pstate - cpu->pstate.min_pstate + 1; | ||
356 | turbo_fp = div_fp(int_tofp(no_turbo), int_tofp(total)); | ||
357 | turbo_pct = 100 - fp_toint(mul_fp(turbo_fp, int_tofp(100))); | ||
358 | return sprintf(buf, "%u\n", turbo_pct); | ||
359 | } | ||
360 | |||
361 | static ssize_t show_num_pstates(struct kobject *kobj, | ||
362 | struct attribute *attr, char *buf) | ||
363 | { | ||
364 | struct cpudata *cpu; | ||
365 | int total; | ||
366 | |||
367 | cpu = all_cpu_data[0]; | ||
368 | total = cpu->pstate.turbo_pstate - cpu->pstate.min_pstate + 1; | ||
369 | return sprintf(buf, "%u\n", total); | ||
370 | } | ||
371 | |||
341 | static ssize_t show_no_turbo(struct kobject *kobj, | 372 | static ssize_t show_no_turbo(struct kobject *kobj, |
342 | struct attribute *attr, char *buf) | 373 | struct attribute *attr, char *buf) |
343 | { | 374 | { |
@@ -404,7 +435,9 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, | |||
404 | ret = sscanf(buf, "%u", &input); | 435 | ret = sscanf(buf, "%u", &input); |
405 | if (ret != 1) | 436 | if (ret != 1) |
406 | return -EINVAL; | 437 | return -EINVAL; |
407 | limits.min_perf_pct = clamp_t(int, input, 0 , 100); | 438 | |
439 | limits.min_sysfs_pct = clamp_t(int, input, 0 , 100); | ||
440 | limits.min_perf_pct = max(limits.min_policy_pct, limits.min_sysfs_pct); | ||
408 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); | 441 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); |
409 | 442 | ||
410 | if (hwp_active) | 443 | if (hwp_active) |
@@ -418,11 +451,15 @@ show_one(min_perf_pct, min_perf_pct); | |||
418 | define_one_global_rw(no_turbo); | 451 | define_one_global_rw(no_turbo); |
419 | define_one_global_rw(max_perf_pct); | 452 | define_one_global_rw(max_perf_pct); |
420 | define_one_global_rw(min_perf_pct); | 453 | define_one_global_rw(min_perf_pct); |
454 | define_one_global_ro(turbo_pct); | ||
455 | define_one_global_ro(num_pstates); | ||
421 | 456 | ||
422 | static struct attribute *intel_pstate_attributes[] = { | 457 | static struct attribute *intel_pstate_attributes[] = { |
423 | &no_turbo.attr, | 458 | &no_turbo.attr, |
424 | &max_perf_pct.attr, | 459 | &max_perf_pct.attr, |
425 | &min_perf_pct.attr, | 460 | &min_perf_pct.attr, |
461 | &turbo_pct.attr, | ||
462 | &num_pstates.attr, | ||
426 | NULL | 463 | NULL |
427 | }; | 464 | }; |
428 | 465 | ||
@@ -825,6 +862,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = { | |||
825 | ICPU(0x46, core_params), | 862 | ICPU(0x46, core_params), |
826 | ICPU(0x47, core_params), | 863 | ICPU(0x47, core_params), |
827 | ICPU(0x4c, byt_params), | 864 | ICPU(0x4c, byt_params), |
865 | ICPU(0x4e, core_params), | ||
828 | ICPU(0x4f, core_params), | 866 | ICPU(0x4f, core_params), |
829 | ICPU(0x56, core_params), | 867 | ICPU(0x56, core_params), |
830 | {} | 868 | {} |
@@ -887,7 +925,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
887 | if (!policy->cpuinfo.max_freq) | 925 | if (!policy->cpuinfo.max_freq) |
888 | return -ENODEV; | 926 | return -ENODEV; |
889 | 927 | ||
890 | if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) { | 928 | if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && |
929 | policy->max >= policy->cpuinfo.max_freq) { | ||
930 | limits.min_policy_pct = 100; | ||
891 | limits.min_perf_pct = 100; | 931 | limits.min_perf_pct = 100; |
892 | limits.min_perf = int_tofp(1); | 932 | limits.min_perf = int_tofp(1); |
893 | limits.max_policy_pct = 100; | 933 | limits.max_policy_pct = 100; |
@@ -897,8 +937,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
897 | return 0; | 937 | return 0; |
898 | } | 938 | } |
899 | 939 | ||
900 | limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; | 940 | limits.min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq; |
901 | limits.min_perf_pct = clamp_t(int, limits.min_perf_pct, 0 , 100); | 941 | limits.min_policy_pct = clamp_t(int, limits.min_policy_pct, 0 , 100); |
942 | limits.min_perf_pct = max(limits.min_policy_pct, limits.min_sysfs_pct); | ||
902 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); | 943 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); |
903 | 944 | ||
904 | limits.max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq; | 945 | limits.max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq; |
@@ -978,6 +1019,7 @@ static struct cpufreq_driver intel_pstate_driver = { | |||
978 | 1019 | ||
979 | static int __initdata no_load; | 1020 | static int __initdata no_load; |
980 | static int __initdata no_hwp; | 1021 | static int __initdata no_hwp; |
1022 | static int __initdata hwp_only; | ||
981 | static unsigned int force_load; | 1023 | static unsigned int force_load; |
982 | 1024 | ||
983 | static int intel_pstate_msrs_not_valid(void) | 1025 | static int intel_pstate_msrs_not_valid(void) |
@@ -1175,6 +1217,9 @@ static int __init intel_pstate_init(void) | |||
1175 | if (cpu_has(c,X86_FEATURE_HWP) && !no_hwp) | 1217 | if (cpu_has(c,X86_FEATURE_HWP) && !no_hwp) |
1176 | intel_pstate_hwp_enable(); | 1218 | intel_pstate_hwp_enable(); |
1177 | 1219 | ||
1220 | if (!hwp_active && hwp_only) | ||
1221 | goto out; | ||
1222 | |||
1178 | rc = cpufreq_register_driver(&intel_pstate_driver); | 1223 | rc = cpufreq_register_driver(&intel_pstate_driver); |
1179 | if (rc) | 1224 | if (rc) |
1180 | goto out; | 1225 | goto out; |
@@ -1209,6 +1254,8 @@ static int __init intel_pstate_setup(char *str) | |||
1209 | no_hwp = 1; | 1254 | no_hwp = 1; |
1210 | if (!strcmp(str, "force")) | 1255 | if (!strcmp(str, "force")) |
1211 | force_load = 1; | 1256 | force_load = 1; |
1257 | if (!strcmp(str, "hwp_only")) | ||
1258 | hwp_only = 1; | ||
1212 | return 0; | 1259 | return 0; |
1213 | } | 1260 | } |
1214 | early_param("intel_pstate", intel_pstate_setup); | 1261 | early_param("intel_pstate", intel_pstate_setup); |