Commit d5dd33d9 authored by Srinivas Pandruvada's avatar Srinivas Pandruvada Committed by Rafael J. Wysocki

cpufreq: intel_pstate: increase precision of performance limits

Even with round up of limits->min_perf and limits->max_perf, in some
cases resultant performance is 100 MHz less than the desired.

For example when the maximum frequency is 3.50 GHz, setting
scaling_min_frequency to 2.3 GHz always results in 2.2 GHz minimum.

Currently the fixed floating point operation uses 8 bit precision for
calculating limits->min_perf and limits->max_perf. For some operations
in this driver the 14 bit precision is used. Using the 14 bit precision
also for calculating limits->min_perf and limits->max_perf, addresses
this issue.

Introduced fp_ext_toint() equivalent to fp_toint() and int_ext_tofp()
equivalent to int_tofp() with 14 bit precision.
Signed-off-by: default avatarSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 46992d6b
...@@ -54,6 +54,8 @@ ...@@ -54,6 +54,8 @@
#define EXT_BITS 6 #define EXT_BITS 6
#define EXT_FRAC_BITS (EXT_BITS + FRAC_BITS) #define EXT_FRAC_BITS (EXT_BITS + FRAC_BITS)
#define fp_ext_toint(X) ((X) >> EXT_FRAC_BITS)
#define int_ext_tofp(X) ((int64_t)(X) << EXT_FRAC_BITS)
static inline int32_t mul_fp(int32_t x, int32_t y) static inline int32_t mul_fp(int32_t x, int32_t y)
{ {
...@@ -351,9 +353,9 @@ static struct perf_limits performance_limits = { ...@@ -351,9 +353,9 @@ static struct perf_limits performance_limits = {
.no_turbo = 0, .no_turbo = 0,
.turbo_disabled = 0, .turbo_disabled = 0,
.max_perf_pct = 100, .max_perf_pct = 100,
.max_perf = int_tofp(1), .max_perf = int_ext_tofp(1),
.min_perf_pct = 100, .min_perf_pct = 100,
.min_perf = int_tofp(1), .min_perf = int_ext_tofp(1),
.max_policy_pct = 100, .max_policy_pct = 100,
.max_sysfs_pct = 100, .max_sysfs_pct = 100,
.min_policy_pct = 0, .min_policy_pct = 0,
...@@ -364,7 +366,7 @@ static struct perf_limits powersave_limits = { ...@@ -364,7 +366,7 @@ static struct perf_limits powersave_limits = {
.no_turbo = 0, .no_turbo = 0,
.turbo_disabled = 0, .turbo_disabled = 0,
.max_perf_pct = 100, .max_perf_pct = 100,
.max_perf = int_tofp(1), .max_perf = int_ext_tofp(1),
.min_perf_pct = 0, .min_perf_pct = 0,
.min_perf = 0, .min_perf = 0,
.max_policy_pct = 100, .max_policy_pct = 100,
...@@ -776,7 +778,7 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b, ...@@ -776,7 +778,7 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
limits->max_perf_pct); limits->max_perf_pct);
limits->max_perf_pct = max(limits->min_perf_pct, limits->max_perf_pct = max(limits->min_perf_pct,
limits->max_perf_pct); limits->max_perf_pct);
limits->max_perf = div_fp(limits->max_perf_pct, 100); limits->max_perf = div_ext_fp(limits->max_perf_pct, 100);
mutex_unlock(&intel_pstate_limits_lock); mutex_unlock(&intel_pstate_limits_lock);
...@@ -804,7 +806,7 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, ...@@ -804,7 +806,7 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
limits->min_perf_pct); limits->min_perf_pct);
limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct = min(limits->max_perf_pct,
limits->min_perf_pct); limits->min_perf_pct);
limits->min_perf = div_fp(limits->min_perf_pct, 100); limits->min_perf = div_ext_fp(limits->min_perf_pct, 100);
mutex_unlock(&intel_pstate_limits_lock); mutex_unlock(&intel_pstate_limits_lock);
...@@ -1189,11 +1191,11 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) ...@@ -1189,11 +1191,11 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
* policy, or by cpu specific default values determined through * policy, or by cpu specific default values determined through
* experimentation. * experimentation.
*/ */
max_perf_adj = fp_toint(max_perf * perf_limits->max_perf); max_perf_adj = fp_ext_toint(max_perf * perf_limits->max_perf);
*max = clamp_t(int, max_perf_adj, *max = clamp_t(int, max_perf_adj,
cpu->pstate.min_pstate, cpu->pstate.turbo_pstate); cpu->pstate.min_pstate, cpu->pstate.turbo_pstate);
min_perf = fp_toint(max_perf * perf_limits->min_perf); min_perf = fp_ext_toint(max_perf * 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);
} }
...@@ -1561,9 +1563,9 @@ static void intel_pstate_set_performance_limits(struct perf_limits *limits) ...@@ -1561,9 +1563,9 @@ static void intel_pstate_set_performance_limits(struct perf_limits *limits)
limits->no_turbo = 0; limits->no_turbo = 0;
limits->turbo_disabled = 0; limits->turbo_disabled = 0;
limits->max_perf_pct = 100; limits->max_perf_pct = 100;
limits->max_perf = int_tofp(1); limits->max_perf = int_ext_tofp(1);
limits->min_perf_pct = 100; limits->min_perf_pct = 100;
limits->min_perf = int_tofp(1); limits->min_perf = int_ext_tofp(1);
limits->max_policy_pct = 100; limits->max_policy_pct = 100;
limits->max_sysfs_pct = 100; limits->max_sysfs_pct = 100;
limits->min_policy_pct = 0; limits->min_policy_pct = 0;
...@@ -1602,10 +1604,10 @@ static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy, ...@@ -1602,10 +1604,10 @@ static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
/* Make sure min_perf_pct <= max_perf_pct */ /* Make sure min_perf_pct <= max_perf_pct */
limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct); limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
limits->min_perf = div_fp(limits->min_perf_pct, 100); limits->min_perf = div_ext_fp(limits->min_perf_pct, 100);
limits->max_perf = div_fp(limits->max_perf_pct, 100); limits->max_perf = div_ext_fp(limits->max_perf_pct, 100);
limits->max_perf = round_up(limits->max_perf, FRAC_BITS); limits->max_perf = round_up(limits->max_perf, EXT_FRAC_BITS);
limits->min_perf = round_up(limits->min_perf, FRAC_BITS); limits->min_perf = round_up(limits->min_perf, EXT_FRAC_BITS);
mutex_unlock(&intel_pstate_limits_lock); mutex_unlock(&intel_pstate_limits_lock);
......
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