intel_pstate: don't touch turbo bit if turbo disabled or unavailable.
commit dd5fbf70f9
upstream.
If turbo is disabled in the BIOS bit 38 should be set in
MSR_IA32_MISC_ENABLE register per section 14.3.2.1 of the SDM Vol 3
document 325384-050US Feb 2014. If this bit is set do *not* attempt
to disable trubo via the MSR_IA32_PERF_CTL register. On some systems
trying to disable turbo via MSR_IA32_PERF_CTL will cause subsequent
writes to MSR_IA32_PERF_CTL not take affect, in fact reading
MSR_IA32_PERF_CTL will not show the IDA/Turbo DISENGAGE bit(32) as
set. A write of bit 32 to zero returns to normal operation.
Also deal with the case where the processor does not support
turbo and the BIOS does not report the fact in MSR_IA32_MISC_ENABLE
but does report the max and turbo P states as the same value.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=64251
Signed-off-by: Dirk Brandewie <dirk.j.brandewie@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
313b12ee56
commit
0493292c25
|
@ -132,6 +132,7 @@ static struct pstate_funcs pstate_funcs;
|
||||||
|
|
||||||
struct perf_limits {
|
struct perf_limits {
|
||||||
int no_turbo;
|
int no_turbo;
|
||||||
|
int turbo_disabled;
|
||||||
int max_perf_pct;
|
int max_perf_pct;
|
||||||
int min_perf_pct;
|
int min_perf_pct;
|
||||||
int32_t max_perf;
|
int32_t max_perf;
|
||||||
|
@ -291,7 +292,10 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
|
||||||
if (ret != 1)
|
if (ret != 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
limits.no_turbo = clamp_t(int, input, 0 , 1);
|
limits.no_turbo = clamp_t(int, input, 0 , 1);
|
||||||
|
if (limits.turbo_disabled) {
|
||||||
|
pr_warn("Turbo disabled by BIOS or unavailable on processor\n");
|
||||||
|
limits.no_turbo = limits.turbo_disabled;
|
||||||
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,7 +389,7 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate)
|
||||||
u32 vid;
|
u32 vid;
|
||||||
|
|
||||||
val = pstate << 8;
|
val = pstate << 8;
|
||||||
if (limits.no_turbo)
|
if (limits.no_turbo && !limits.turbo_disabled)
|
||||||
val |= (u64)1 << 32;
|
val |= (u64)1 << 32;
|
||||||
|
|
||||||
vid_fp = cpudata->vid.min + mul_fp(
|
vid_fp = cpudata->vid.min + mul_fp(
|
||||||
|
@ -452,7 +456,7 @@ static void core_set_pstate(struct cpudata *cpudata, int pstate)
|
||||||
u64 val;
|
u64 val;
|
||||||
|
|
||||||
val = pstate << 8;
|
val = pstate << 8;
|
||||||
if (limits.no_turbo)
|
if (limits.no_turbo && !limits.turbo_disabled)
|
||||||
val |= (u64)1 << 32;
|
val |= (u64)1 << 32;
|
||||||
|
|
||||||
wrmsrl(MSR_IA32_PERF_CTL, val);
|
wrmsrl(MSR_IA32_PERF_CTL, val);
|
||||||
|
@ -750,7 +754,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
|
||||||
limits.min_perf = int_tofp(1);
|
limits.min_perf = int_tofp(1);
|
||||||
limits.max_perf_pct = 100;
|
limits.max_perf_pct = 100;
|
||||||
limits.max_perf = int_tofp(1);
|
limits.max_perf = int_tofp(1);
|
||||||
limits.no_turbo = 0;
|
limits.no_turbo = limits.turbo_disabled;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq;
|
limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq;
|
||||||
|
@ -790,6 +794,7 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
struct cpudata *cpu;
|
struct cpudata *cpu;
|
||||||
int rc;
|
int rc;
|
||||||
|
u64 misc_en;
|
||||||
|
|
||||||
rc = intel_pstate_init_cpu(policy->cpu);
|
rc = intel_pstate_init_cpu(policy->cpu);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -797,8 +802,13 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
|
||||||
|
|
||||||
cpu = all_cpu_data[policy->cpu];
|
cpu = all_cpu_data[policy->cpu];
|
||||||
|
|
||||||
if (!limits.no_turbo &&
|
rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
|
||||||
limits.min_perf_pct == 100 && limits.max_perf_pct == 100)
|
if (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
|
||||||
|
cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) {
|
||||||
|
limits.turbo_disabled = 1;
|
||||||
|
limits.no_turbo = 1;
|
||||||
|
}
|
||||||
|
if (limits.min_perf_pct == 100 && limits.max_perf_pct == 100)
|
||||||
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
|
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
|
||||||
else
|
else
|
||||||
policy->policy = CPUFREQ_POLICY_POWERSAVE;
|
policy->policy = CPUFREQ_POLICY_POWERSAVE;
|
||||||
|
|
Loading…
Reference in New Issue