Commit e3a50084 authored by Gabriele Mazzotta's avatar Gabriele Mazzotta Committed by Luis Henriques

cpufreq: intel_pstate: Reflect current no_turbo state correctly

commit 4521e1a0 upstream.

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=83151Signed-off-by: default avatarGabriele Mazzotta <gabriele.mzt@gmail.com>
Signed-off-by: default avatarDirk Brandewie <dirk.j.brandewie@intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
[ luis: backported to 3.16: adjusted context ]
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent 98198820
...@@ -139,6 +139,7 @@ struct perf_limits { ...@@ -139,6 +139,7 @@ struct perf_limits {
static struct perf_limits limits = { static struct perf_limits limits = {
.no_turbo = 0, .no_turbo = 0,
.turbo_disabled = 0,
.max_perf_pct = 100, .max_perf_pct = 100,
.max_perf = int_tofp(1), .max_perf = int_tofp(1),
.min_perf_pct = 0, .min_perf_pct = 0,
...@@ -223,6 +224,18 @@ static inline void intel_pstate_reset_all_pid(void) ...@@ -223,6 +224,18 @@ static inline void intel_pstate_reset_all_pid(void)
} }
} }
static inline void update_turbo_state(void)
{
u64 misc_en;
struct cpudata *cpu;
cpu = all_cpu_data[0];
rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
limits.turbo_disabled =
(misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
cpu->pstate.max_pstate == cpu->pstate.turbo_pstate);
}
/************************** debugfs begin ************************/ /************************** debugfs begin ************************/
static int pid_param_set(void *data, u64 val) static int pid_param_set(void *data, u64 val)
{ {
...@@ -279,6 +292,20 @@ static void intel_pstate_debug_expose_params(void) ...@@ -279,6 +292,20 @@ static void intel_pstate_debug_expose_params(void)
return sprintf(buf, "%u\n", limits.object); \ return sprintf(buf, "%u\n", limits.object); \
} }
static ssize_t show_no_turbo(struct kobject *kobj,
struct attribute *attr, char *buf)
{
ssize_t ret;
update_turbo_state();
if (limits.turbo_disabled)
ret = sprintf(buf, "%u\n", limits.turbo_disabled);
else
ret = sprintf(buf, "%u\n", limits.no_turbo);
return ret;
}
static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
const char *buf, size_t count) const char *buf, size_t count)
{ {
...@@ -287,11 +314,14 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, ...@@ -287,11 +314,14 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
ret = sscanf(buf, "%u", &input); ret = sscanf(buf, "%u", &input);
if (ret != 1) if (ret != 1)
return -EINVAL; return -EINVAL;
limits.no_turbo = clamp_t(int, input, 0 , 1);
update_turbo_state();
if (limits.turbo_disabled) { if (limits.turbo_disabled) {
pr_warn("Turbo disabled by BIOS or unavailable on processor\n"); pr_warn("Turbo disabled by BIOS or unavailable on processor\n");
limits.no_turbo = limits.turbo_disabled; return -EPERM;
} }
limits.no_turbo = clamp_t(int, input, 0, 1);
return count; return count;
} }
...@@ -324,7 +354,6 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, ...@@ -324,7 +354,6 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
return count; return count;
} }
show_one(no_turbo, no_turbo);
show_one(max_perf_pct, max_perf_pct); show_one(max_perf_pct, max_perf_pct);
show_one(min_perf_pct, min_perf_pct); show_one(min_perf_pct, min_perf_pct);
...@@ -499,7 +528,8 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) ...@@ -499,7 +528,8 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
int max_perf = cpu->pstate.turbo_pstate; int max_perf = cpu->pstate.turbo_pstate;
int max_perf_adj; int max_perf_adj;
int min_perf; int min_perf;
if (limits.no_turbo)
if (limits.no_turbo || limits.turbo_disabled)
max_perf = cpu->pstate.max_pstate; max_perf = cpu->pstate.max_pstate;
max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf)); max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf));
...@@ -515,6 +545,8 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) ...@@ -515,6 +545,8 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
{ {
int max_perf, min_perf; int max_perf, min_perf;
update_turbo_state();
intel_pstate_get_min_max(cpu, &min_perf, &max_perf); intel_pstate_get_min_max(cpu, &min_perf, &max_perf);
pstate = clamp_t(int, pstate, min_perf, max_perf); pstate = clamp_t(int, pstate, min_perf, max_perf);
...@@ -745,7 +777,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) ...@@ -745,7 +777,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
limits.max_policy_pct = 100; limits.max_policy_pct = 100;
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 = limits.turbo_disabled; limits.no_turbo = 0;
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;
...@@ -788,7 +820,6 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) ...@@ -788,7 +820,6 @@ 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)
...@@ -796,12 +827,6 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) ...@@ -796,12 +827,6 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
cpu = all_cpu_data[policy->cpu]; cpu = all_cpu_data[policy->cpu];
rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
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) if (limits.min_perf_pct == 100 && limits.max_perf_pct == 100)
policy->policy = CPUFREQ_POLICY_PERFORMANCE; policy->policy = CPUFREQ_POLICY_PERFORMANCE;
else else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment