diff options
-rw-r--r-- | Documentation/cpu-freq/intel-pstate.txt | 7 | ||||
-rw-r--r-- | drivers/cpufreq/Makefile | 2 | ||||
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 35 |
3 files changed, 28 insertions, 16 deletions
diff --git a/Documentation/cpu-freq/intel-pstate.txt b/Documentation/cpu-freq/intel-pstate.txt index e742d21dbd96..a69ffe1d54d5 100644 --- a/Documentation/cpu-freq/intel-pstate.txt +++ b/Documentation/cpu-freq/intel-pstate.txt | |||
@@ -15,10 +15,13 @@ New sysfs files for controlling P state selection have been added to | |||
15 | /sys/devices/system/cpu/intel_pstate/ | 15 | /sys/devices/system/cpu/intel_pstate/ |
16 | 16 | ||
17 | max_perf_pct: limits the maximum P state that will be requested by | 17 | max_perf_pct: limits the maximum P state that will be requested by |
18 | the driver stated as a percentage of the available performance. | 18 | the driver stated as a percentage of the available performance. The |
19 | available (P states) performance may be reduced by the no_turbo | ||
20 | setting described below. | ||
19 | 21 | ||
20 | min_perf_pct: limits the minimum P state that will be requested by | 22 | min_perf_pct: limits the minimum P state that will be requested by |
21 | the driver stated as a percentage of the available performance. | 23 | the driver stated as a percentage of the max (non-turbo) |
24 | performance level. | ||
22 | 25 | ||
23 | no_turbo: limits the driver to selecting P states below the turbo | 26 | no_turbo: limits the driver to selecting P states below the turbo |
24 | frequency range. | 27 | frequency range. |
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 738c8b7b17dc..db6d9a2fea4d 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile | |||
@@ -49,7 +49,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o | |||
49 | # LITTLE drivers, so that it is probed last. | 49 | # LITTLE drivers, so that it is probed last. |
50 | obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o | 50 | obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o |
51 | 51 | ||
52 | obj-$(CONFIG_ARCH_DAVINCI_DA850) += davinci-cpufreq.o | 52 | obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o |
53 | obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o | 53 | obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o |
54 | obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += exynos-cpufreq.o | 54 | obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += exynos-cpufreq.o |
55 | obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o | 55 | obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o |
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 924bb2d42b1c..86631cb6f7de 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -128,6 +128,7 @@ static struct pstate_funcs pstate_funcs; | |||
128 | 128 | ||
129 | struct perf_limits { | 129 | struct perf_limits { |
130 | int no_turbo; | 130 | int no_turbo; |
131 | int turbo_disabled; | ||
131 | int max_perf_pct; | 132 | int max_perf_pct; |
132 | int min_perf_pct; | 133 | int min_perf_pct; |
133 | int32_t max_perf; | 134 | int32_t max_perf; |
@@ -287,7 +288,10 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, | |||
287 | if (ret != 1) | 288 | if (ret != 1) |
288 | return -EINVAL; | 289 | return -EINVAL; |
289 | limits.no_turbo = clamp_t(int, input, 0 , 1); | 290 | limits.no_turbo = clamp_t(int, input, 0 , 1); |
290 | 291 | if (limits.turbo_disabled) { | |
292 | pr_warn("Turbo disabled by BIOS or unavailable on processor\n"); | ||
293 | limits.no_turbo = limits.turbo_disabled; | ||
294 | } | ||
291 | return count; | 295 | return count; |
292 | } | 296 | } |
293 | 297 | ||
@@ -357,21 +361,21 @@ static int byt_get_min_pstate(void) | |||
357 | { | 361 | { |
358 | u64 value; | 362 | u64 value; |
359 | rdmsrl(BYT_RATIOS, value); | 363 | rdmsrl(BYT_RATIOS, value); |
360 | return (value >> 8) & 0x3F; | 364 | return (value >> 8) & 0x7F; |
361 | } | 365 | } |
362 | 366 | ||
363 | static int byt_get_max_pstate(void) | 367 | static int byt_get_max_pstate(void) |
364 | { | 368 | { |
365 | u64 value; | 369 | u64 value; |
366 | rdmsrl(BYT_RATIOS, value); | 370 | rdmsrl(BYT_RATIOS, value); |
367 | return (value >> 16) & 0x3F; | 371 | return (value >> 16) & 0x7F; |
368 | } | 372 | } |
369 | 373 | ||
370 | static int byt_get_turbo_pstate(void) | 374 | static int byt_get_turbo_pstate(void) |
371 | { | 375 | { |
372 | u64 value; | 376 | u64 value; |
373 | rdmsrl(BYT_TURBO_RATIOS, value); | 377 | rdmsrl(BYT_TURBO_RATIOS, value); |
374 | return value & 0x3F; | 378 | return value & 0x7F; |
375 | } | 379 | } |
376 | 380 | ||
377 | static void byt_set_pstate(struct cpudata *cpudata, int pstate) | 381 | static void byt_set_pstate(struct cpudata *cpudata, int pstate) |
@@ -381,7 +385,7 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate) | |||
381 | u32 vid; | 385 | u32 vid; |
382 | 386 | ||
383 | val = pstate << 8; | 387 | val = pstate << 8; |
384 | if (limits.no_turbo) | 388 | if (limits.no_turbo && !limits.turbo_disabled) |
385 | val |= (u64)1 << 32; | 389 | val |= (u64)1 << 32; |
386 | 390 | ||
387 | vid_fp = cpudata->vid.min + mul_fp( | 391 | vid_fp = cpudata->vid.min + mul_fp( |
@@ -405,8 +409,8 @@ static void byt_get_vid(struct cpudata *cpudata) | |||
405 | 409 | ||
406 | 410 | ||
407 | rdmsrl(BYT_VIDS, value); | 411 | rdmsrl(BYT_VIDS, value); |
408 | cpudata->vid.min = int_tofp((value >> 8) & 0x3f); | 412 | cpudata->vid.min = int_tofp((value >> 8) & 0x7f); |
409 | cpudata->vid.max = int_tofp((value >> 16) & 0x3f); | 413 | cpudata->vid.max = int_tofp((value >> 16) & 0x7f); |
410 | cpudata->vid.ratio = div_fp( | 414 | cpudata->vid.ratio = div_fp( |
411 | cpudata->vid.max - cpudata->vid.min, | 415 | cpudata->vid.max - cpudata->vid.min, |
412 | int_tofp(cpudata->pstate.max_pstate - | 416 | int_tofp(cpudata->pstate.max_pstate - |
@@ -448,7 +452,7 @@ static void core_set_pstate(struct cpudata *cpudata, int pstate) | |||
448 | u64 val; | 452 | u64 val; |
449 | 453 | ||
450 | val = pstate << 8; | 454 | val = pstate << 8; |
451 | if (limits.no_turbo) | 455 | if (limits.no_turbo && !limits.turbo_disabled) |
452 | val |= (u64)1 << 32; | 456 | val |= (u64)1 << 32; |
453 | 457 | ||
454 | wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val); | 458 | wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val); |
@@ -696,9 +700,8 @@ static int intel_pstate_init_cpu(unsigned int cpunum) | |||
696 | 700 | ||
697 | cpu = all_cpu_data[cpunum]; | 701 | cpu = all_cpu_data[cpunum]; |
698 | 702 | ||
699 | intel_pstate_get_cpu_pstates(cpu); | ||
700 | |||
701 | cpu->cpu = cpunum; | 703 | cpu->cpu = cpunum; |
704 | intel_pstate_get_cpu_pstates(cpu); | ||
702 | 705 | ||
703 | init_timer_deferrable(&cpu->timer); | 706 | init_timer_deferrable(&cpu->timer); |
704 | cpu->timer.function = intel_pstate_timer_func; | 707 | cpu->timer.function = intel_pstate_timer_func; |
@@ -741,7 +744,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
741 | limits.min_perf = int_tofp(1); | 744 | limits.min_perf = int_tofp(1); |
742 | limits.max_perf_pct = 100; | 745 | limits.max_perf_pct = 100; |
743 | limits.max_perf = int_tofp(1); | 746 | limits.max_perf = int_tofp(1); |
744 | limits.no_turbo = 0; | 747 | limits.no_turbo = limits.turbo_disabled; |
745 | return 0; | 748 | return 0; |
746 | } | 749 | } |
747 | limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; | 750 | limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; |
@@ -784,6 +787,7 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) | |||
784 | { | 787 | { |
785 | struct cpudata *cpu; | 788 | struct cpudata *cpu; |
786 | int rc; | 789 | int rc; |
790 | u64 misc_en; | ||
787 | 791 | ||
788 | rc = intel_pstate_init_cpu(policy->cpu); | 792 | rc = intel_pstate_init_cpu(policy->cpu); |
789 | if (rc) | 793 | if (rc) |
@@ -791,8 +795,13 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) | |||
791 | 795 | ||
792 | cpu = all_cpu_data[policy->cpu]; | 796 | cpu = all_cpu_data[policy->cpu]; |
793 | 797 | ||
794 | if (!limits.no_turbo && | 798 | rdmsrl(MSR_IA32_MISC_ENABLE, misc_en); |
795 | limits.min_perf_pct == 100 && limits.max_perf_pct == 100) | 799 | if (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE || |
800 | cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) { | ||
801 | limits.turbo_disabled = 1; | ||
802 | limits.no_turbo = 1; | ||
803 | } | ||
804 | if (limits.min_perf_pct == 100 && limits.max_perf_pct == 100) | ||
796 | policy->policy = CPUFREQ_POLICY_PERFORMANCE; | 805 | policy->policy = CPUFREQ_POLICY_PERFORMANCE; |
797 | else | 806 | else |
798 | policy->policy = CPUFREQ_POLICY_POWERSAVE; | 807 | policy->policy = CPUFREQ_POLICY_POWERSAVE; |