summaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/intel_pstate.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq/intel_pstate.c')
-rw-r--r--drivers/cpufreq/intel_pstate.c131
1 files changed, 53 insertions, 78 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 86631cb6f7de..c5eac949760d 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -37,7 +37,6 @@
#define BYT_TURBO_RATIOS 0x66c
#define BYT_TURBO_VIDS 0x66d
-
#define FRAC_BITS 8
#define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
#define fp_toint(X) ((X) >> FRAC_BITS)
@@ -50,7 +49,7 @@ static inline int32_t mul_fp(int32_t x, int32_t y)
static inline int32_t div_fp(int32_t x, int32_t y)
{
- return div_s64((int64_t)x << FRAC_BITS, (int64_t)y);
+ return div_s64((int64_t)x << FRAC_BITS, y);
}
struct sample {
@@ -148,7 +147,7 @@ static struct perf_limits limits = {
};
static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
- int deadband, int integral) {
+ int deadband, int integral) {
pid->setpoint = setpoint;
pid->deadband = deadband;
pid->integral = int_tofp(integral);
@@ -167,7 +166,6 @@ static inline void pid_i_gain_set(struct _pid *pid, int percent)
static inline void pid_d_gain_set(struct _pid *pid, int percent)
{
-
pid->d_gain = div_fp(int_tofp(percent), int_tofp(100));
}
@@ -207,16 +205,13 @@ static inline void intel_pstate_busy_pid_reset(struct cpudata *cpu)
pid_d_gain_set(&cpu->pid, pid_params.d_gain_pct);
pid_i_gain_set(&cpu->pid, pid_params.i_gain_pct);
- pid_reset(&cpu->pid,
- pid_params.setpoint,
- 100,
- pid_params.deadband,
- 0);
+ pid_reset(&cpu->pid, pid_params.setpoint, 100, pid_params.deadband, 0);
}
static inline void intel_pstate_reset_all_pid(void)
{
unsigned int cpu;
+
for_each_online_cpu(cpu) {
if (all_cpu_data[cpu])
intel_pstate_busy_pid_reset(all_cpu_data[cpu]);
@@ -230,13 +225,13 @@ static int pid_param_set(void *data, u64 val)
intel_pstate_reset_all_pid();
return 0;
}
+
static int pid_param_get(void *data, u64 *val)
{
*val = *(u32 *)data;
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(fops_pid_param, pid_param_get,
- pid_param_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(fops_pid_param, pid_param_get, pid_param_set, "%llu\n");
struct pid_param {
char *name;
@@ -253,9 +248,9 @@ static struct pid_param pid_files[] = {
{NULL, NULL}
};
-static struct dentry *debugfs_parent;
-static void intel_pstate_debug_expose_params(void)
+static void __init intel_pstate_debug_expose_params(void)
{
+ struct dentry *debugfs_parent;
int i = 0;
debugfs_parent = debugfs_create_dir("pstate_snb", NULL);
@@ -263,8 +258,8 @@ static void intel_pstate_debug_expose_params(void)
return;
while (pid_files[i].name) {
debugfs_create_file(pid_files[i].name, 0660,
- debugfs_parent, pid_files[i].value,
- &fops_pid_param);
+ debugfs_parent, pid_files[i].value,
+ &fops_pid_param);
i++;
}
}
@@ -280,10 +275,11 @@ static void intel_pstate_debug_expose_params(void)
}
static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
+ const char *buf, size_t count)
{
unsigned int input;
int ret;
+
ret = sscanf(buf, "%u", &input);
if (ret != 1)
return -EINVAL;
@@ -296,10 +292,11 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
}
static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
+ const char *buf, size_t count)
{
unsigned int input;
int ret;
+
ret = sscanf(buf, "%u", &input);
if (ret != 1)
return -EINVAL;
@@ -307,14 +304,16 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
limits.max_sysfs_pct = clamp_t(int, input, 0 , 100);
limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
+
return count;
}
static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
+ const char *buf, size_t count)
{
unsigned int input;
int ret;
+
ret = sscanf(buf, "%u", &input);
if (ret != 1)
return -EINVAL;
@@ -342,17 +341,16 @@ static struct attribute *intel_pstate_attributes[] = {
static struct attribute_group intel_pstate_attr_group = {
.attrs = intel_pstate_attributes,
};
-static struct kobject *intel_pstate_kobject;
-static void intel_pstate_sysfs_expose_params(void)
+static void __init intel_pstate_sysfs_expose_params(void)
{
+ struct kobject *intel_pstate_kobject;
int rc;
intel_pstate_kobject = kobject_create_and_add("intel_pstate",
&cpu_subsys.dev_root->kobj);
BUG_ON(!intel_pstate_kobject);
- rc = sysfs_create_group(intel_pstate_kobject,
- &intel_pstate_attr_group);
+ rc = sysfs_create_group(intel_pstate_kobject, &intel_pstate_attr_group);
BUG_ON(rc);
}
@@ -360,6 +358,7 @@ static void intel_pstate_sysfs_expose_params(void)
static int byt_get_min_pstate(void)
{
u64 value;
+
rdmsrl(BYT_RATIOS, value);
return (value >> 8) & 0x7F;
}
@@ -367,6 +366,7 @@ static int byt_get_min_pstate(void)
static int byt_get_max_pstate(void)
{
u64 value;
+
rdmsrl(BYT_RATIOS, value);
return (value >> 16) & 0x7F;
}
@@ -374,6 +374,7 @@ static int byt_get_max_pstate(void)
static int byt_get_turbo_pstate(void)
{
u64 value;
+
rdmsrl(BYT_TURBO_RATIOS, value);
return value & 0x7F;
}
@@ -407,7 +408,6 @@ static void byt_get_vid(struct cpudata *cpudata)
{
u64 value;
-
rdmsrl(BYT_VIDS, value);
cpudata->vid.min = int_tofp((value >> 8) & 0x7f);
cpudata->vid.max = int_tofp((value >> 16) & 0x7f);
@@ -420,10 +420,10 @@ static void byt_get_vid(struct cpudata *cpudata)
cpudata->vid.turbo = value & 0x7f;
}
-
static int core_get_min_pstate(void)
{
u64 value;
+
rdmsrl(MSR_PLATFORM_INFO, value);
return (value >> 40) & 0xFF;
}
@@ -431,6 +431,7 @@ static int core_get_min_pstate(void)
static int core_get_max_pstate(void)
{
u64 value;
+
rdmsrl(MSR_PLATFORM_INFO, value);
return (value >> 8) & 0xFF;
}
@@ -439,9 +440,10 @@ static int core_get_turbo_pstate(void)
{
u64 value;
int nont, ret;
+
rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value);
nont = core_get_max_pstate();
- ret = ((value) & 255);
+ ret = (value) & 255;
if (ret <= nont)
ret = nont;
return ret;
@@ -493,12 +495,12 @@ static struct cpu_defaults byt_params = {
},
};
-
static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
{
int max_perf = cpu->pstate.turbo_pstate;
int max_perf_adj;
int min_perf;
+
if (limits.no_turbo)
max_perf = cpu->pstate.max_pstate;
@@ -507,8 +509,7 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
cpu->pstate.min_pstate, cpu->pstate.turbo_pstate);
min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.min_perf));
- *min = clamp_t(int, min_perf,
- cpu->pstate.min_pstate, max_perf);
+ *min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf);
}
static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
@@ -529,21 +530,6 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
pstate_funcs.set(cpu, pstate);
}
-static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps)
-{
- int target;
- target = cpu->pstate.current_pstate + steps;
-
- intel_pstate_set_pstate(cpu, target);
-}
-
-static inline void intel_pstate_pstate_decrease(struct cpudata *cpu, int steps)
-{
- int target;
- target = cpu->pstate.current_pstate - steps;
- intel_pstate_set_pstate(cpu, target);
-}
-
static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
{
cpu->pstate.min_pstate = pstate_funcs.get_min();
@@ -559,13 +545,9 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu)
{
struct sample *sample = &cpu->sample;
int64_t core_pct;
- int32_t rem;
core_pct = int_tofp(sample->aperf) * int_tofp(100);
- core_pct = div_u64_rem(core_pct, int_tofp(sample->mperf), &rem);
-
- if ((rem << 1) >= int_tofp(sample->mperf))
- core_pct += 1;
+ core_pct = div64_u64(core_pct, int_tofp(sample->mperf));
sample->freq = fp_toint(
mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct));
@@ -576,12 +558,12 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu)
static inline void intel_pstate_sample(struct cpudata *cpu)
{
u64 aperf, mperf;
+ unsigned long flags;
+ local_irq_save(flags);
rdmsrl(MSR_IA32_APERF, aperf);
rdmsrl(MSR_IA32_MPERF, mperf);
-
- aperf = aperf >> FRAC_BITS;
- mperf = mperf >> FRAC_BITS;
+ local_irq_restore(flags);
cpu->last_sample_time = cpu->sample.time;
cpu->sample.time = ktime_get();
@@ -598,10 +580,9 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
{
- int sample_time, delay;
+ int delay;
- sample_time = pid_params.sample_rate_ms;
- delay = msecs_to_jiffies(sample_time);
+ delay = msecs_to_jiffies(pid_params.sample_rate_ms);
mod_timer_pinned(&cpu->timer, jiffies + delay);
}
@@ -616,12 +597,12 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
current_pstate = int_tofp(cpu->pstate.current_pstate);
core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
- sample_time = (pid_params.sample_rate_ms * USEC_PER_MSEC);
+ sample_time = pid_params.sample_rate_ms * USEC_PER_MSEC;
duration_us = (u32) ktime_us_delta(cpu->sample.time,
- cpu->last_sample_time);
+ cpu->last_sample_time);
if (duration_us > sample_time * 3) {
sample_ratio = div_fp(int_tofp(sample_time),
- int_tofp(duration_us));
+ int_tofp(duration_us));
core_busy = mul_fp(core_busy, sample_ratio);
}
@@ -632,20 +613,15 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
{
int32_t busy_scaled;
struct _pid *pid;
- signed int ctl = 0;
- int steps;
+ signed int ctl;
pid = &cpu->pid;
busy_scaled = intel_pstate_get_scaled_busy(cpu);
ctl = pid_calc(pid, busy_scaled);
- steps = abs(ctl);
-
- if (ctl < 0)
- intel_pstate_pstate_increase(cpu, steps);
- else
- intel_pstate_pstate_decrease(cpu, steps);
+ /* Negative values of ctl increase the pstate and vice versa */
+ intel_pstate_set_pstate(cpu, cpu->pstate.current_pstate - ctl);
}
static void intel_pstate_timer_func(unsigned long __data)
@@ -705,8 +681,7 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
init_timer_deferrable(&cpu->timer);
cpu->timer.function = intel_pstate_timer_func;
- cpu->timer.data =
- (unsigned long)cpu;
+ cpu->timer.data = (unsigned long)cpu;
cpu->timer.expires = jiffies + HZ/100;
intel_pstate_busy_pid_reset(cpu);
intel_pstate_sample(cpu);
@@ -751,7 +726,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
limits.min_perf_pct = clamp_t(int, limits.min_perf_pct, 0 , 100);
limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100));
- limits.max_policy_pct = policy->max * 100 / policy->cpuinfo.max_freq;
+ limits.max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq;
limits.max_policy_pct = clamp_t(int, limits.max_policy_pct, 0 , 100);
limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
@@ -763,8 +738,8 @@ static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
{
cpufreq_verify_within_cpu_limits(policy);
- if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
- (policy->policy != CPUFREQ_POLICY_PERFORMANCE))
+ if (policy->policy != CPUFREQ_POLICY_POWERSAVE &&
+ policy->policy != CPUFREQ_POLICY_PERFORMANCE)
return -EINVAL;
return 0;
@@ -797,7 +772,7 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
if (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
- cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) {
+ cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) {
limits.turbo_disabled = 1;
limits.no_turbo = 1;
}
@@ -839,8 +814,8 @@ static int intel_pstate_msrs_not_valid(void)
rdmsrl(MSR_IA32_MPERF, mperf);
if (!pstate_funcs.get_max() ||
- !pstate_funcs.get_min() ||
- !pstate_funcs.get_turbo())
+ !pstate_funcs.get_min() ||
+ !pstate_funcs.get_turbo())
return -ENODEV;
rdmsrl(MSR_IA32_APERF, tmp);
@@ -922,14 +897,14 @@ static bool intel_pstate_platform_pwr_mgmt_exists(void)
struct acpi_table_header hdr;
struct hw_vendor_info *v_info;
- if (acpi_disabled
- || ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr)))
+ if (acpi_disabled ||
+ ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr)))
return false;
for (v_info = vendor_info; v_info->valid; v_info++) {
- if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE)
- && !strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE)
- && intel_pstate_no_acpi_pss())
+ if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE) &&
+ !strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
+ intel_pstate_no_acpi_pss())
return true;
}
OpenPOWER on IntegriCloud