diff options
Diffstat (limited to 'drivers/cpufreq/intel_pstate.c')
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 131 |
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; } |