Skip to content

Commit e4c204c

Browse files
committed
cpufreq: intel_pstate: Avoid percentages in limits-related computations
Currently, intel_pstate_update_perf_limits() first converts the policy minimum and maximum limits into percentages of the maximum turbo frequency (rounding up to an integer) and then converts these percentages to fractions (by using fixed-point arithmetic to divide them by 100). That introduces a rounding error unnecessarily, because the fractions can be obtained by carrying out fixed-point divisions directly on the input numbers. Rework the computations in intel_pstate_hwp_set() to use fractions instead of percentages (and drop redundant local variables from there) and modify intel_pstate_update_perf_limits() to compute the fractions directly and percentages out of them. While at it, introduce percent_ext_fp() for converting percentages to fractions (with extended number of fraction bits) and use it in the computations. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 3f8ed54 commit e4c204c

File tree

1 file changed

+28
-28
lines changed

1 file changed

+28
-28
lines changed

drivers/cpufreq/intel_pstate.c

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ static inline u64 div_ext_fp(u64 x, u64 y)
8484
return div64_u64(x << EXT_FRAC_BITS, y);
8585
}
8686

87+
static inline int32_t percent_ext_fp(int percent)
88+
{
89+
return div_ext_fp(percent, 100);
90+
}
91+
8792
/**
8893
* struct sample - Store performance sample
8994
* @core_avg_perf: Ratio of APERF/MPERF which is the actual average
@@ -850,7 +855,6 @@ static void intel_pstate_hwp_set(struct cpufreq_policy *policy)
850855
u64 value, cap;
851856

852857
for_each_cpu(cpu, policy->cpus) {
853-
int max_perf_pct, min_perf_pct;
854858
struct cpudata *cpu_data = all_cpu_data[cpu];
855859
s16 epp;
856860

@@ -864,16 +868,14 @@ static void intel_pstate_hwp_set(struct cpufreq_policy *policy)
864868
else
865869
hw_max = HWP_HIGHEST_PERF(cap);
866870

867-
max_perf_pct = perf_limits->max_perf_pct;
868-
min_perf_pct = perf_limits->min_perf_pct;
869-
min = hw_max * min_perf_pct / 100;
871+
min = fp_ext_toint(hw_max * perf_limits->min_perf);
870872

871873
rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value);
872874

873875
value &= ~HWP_MIN_PERF(~0L);
874876
value |= HWP_MIN_PERF(min);
875877

876-
max = hw_max * max_perf_pct / 100;
878+
max = fp_ext_toint(hw_max * perf_limits->max_perf);
877879
value &= ~HWP_MAX_PERF(~0L);
878880
value |= HWP_MAX_PERF(max);
879881

@@ -1223,7 +1225,7 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
12231225
limits->max_perf_pct);
12241226
limits->max_perf_pct = max(limits->min_perf_pct,
12251227
limits->max_perf_pct);
1226-
limits->max_perf = div_ext_fp(limits->max_perf_pct, 100);
1228+
limits->max_perf = percent_ext_fp(limits->max_perf_pct);
12271229

12281230
intel_pstate_update_policies();
12291231

@@ -1260,7 +1262,7 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
12601262
limits->min_perf_pct);
12611263
limits->min_perf_pct = min(limits->max_perf_pct,
12621264
limits->min_perf_pct);
1263-
limits->min_perf = div_ext_fp(limits->min_perf_pct, 100);
1265+
limits->min_perf = percent_ext_fp(limits->min_perf_pct);
12641266

12651267
intel_pstate_update_policies();
12661268

@@ -2078,36 +2080,34 @@ static void intel_pstate_clear_update_util_hook(unsigned int cpu)
20782080
static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
20792081
struct perf_limits *limits)
20802082
{
2083+
int32_t max_policy_perf, min_policy_perf;
20812084

2082-
limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100,
2083-
policy->cpuinfo.max_freq);
2084-
limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0, 100);
2085+
max_policy_perf = div_ext_fp(policy->max, policy->cpuinfo.max_freq);
2086+
max_policy_perf = clamp_t(int32_t, max_policy_perf, 0, int_ext_tofp(1));
20852087
if (policy->max == policy->min) {
2086-
limits->min_policy_pct = limits->max_policy_pct;
2088+
min_policy_perf = max_policy_perf;
20872089
} else {
2088-
limits->min_policy_pct = DIV_ROUND_UP(policy->min * 100,
2089-
policy->cpuinfo.max_freq);
2090-
limits->min_policy_pct = clamp_t(int, limits->min_policy_pct,
2091-
0, 100);
2090+
min_policy_perf = div_ext_fp(policy->min,
2091+
policy->cpuinfo.max_freq);
2092+
min_policy_perf = clamp_t(int32_t, min_policy_perf,
2093+
0, max_policy_perf);
20922094
}
20932095

2094-
/* Normalize user input to [min_policy_pct, max_policy_pct] */
2095-
limits->min_perf_pct = max(limits->min_policy_pct,
2096-
limits->min_sysfs_pct);
2097-
limits->min_perf_pct = min(limits->max_policy_pct,
2098-
limits->min_perf_pct);
2099-
limits->max_perf_pct = min(limits->max_policy_pct,
2100-
limits->max_sysfs_pct);
2101-
limits->max_perf_pct = max(limits->min_policy_pct,
2102-
limits->max_perf_pct);
2096+
/* Normalize user input to [min_perf, max_perf] */
2097+
limits->min_perf = max(min_policy_perf,
2098+
percent_ext_fp(limits->min_sysfs_pct));
2099+
limits->min_perf = min(limits->min_perf, max_policy_perf);
2100+
limits->max_perf = min(max_policy_perf,
2101+
percent_ext_fp(limits->max_sysfs_pct));
2102+
limits->max_perf = max(min_policy_perf, limits->max_perf);
21032103

2104-
/* Make sure min_perf_pct <= max_perf_pct */
2105-
limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
2104+
/* Make sure min_perf <= max_perf */
2105+
limits->min_perf = min(limits->min_perf, limits->max_perf);
21062106

2107-
limits->min_perf = div_ext_fp(limits->min_perf_pct, 100);
2108-
limits->max_perf = div_ext_fp(limits->max_perf_pct, 100);
21092107
limits->max_perf = round_up(limits->max_perf, EXT_FRAC_BITS);
21102108
limits->min_perf = round_up(limits->min_perf, EXT_FRAC_BITS);
2109+
limits->max_perf_pct = fp_ext_toint(limits->max_perf * 100);
2110+
limits->min_perf_pct = fp_ext_toint(limits->min_perf * 100);
21112111

21122112
pr_debug("cpu:%d max_perf_pct:%d min_perf_pct:%d\n", policy->cpu,
21132113
limits->max_perf_pct, limits->min_perf_pct);

0 commit comments

Comments
 (0)