Skip to content

Commit 1a4fe38

Browse files
spandruvadarafaeljw
authored andcommitted
cpufreq: intel_pstate: Remove max/min fractions to limit performance
In the current model the max/min perf limits are a fraction of current user space limits to the allowed max_freq or 100% for global limits. This results in wrong ratio limits calculation because of rounding issues for some user space limits. Initially we tried to solve this issue by issue by having more shift bits to increase precision. Still there are isolated cases where we still have error. This can be avoided by using ratios all together. Since the way we get cpuinfo.max_freq is by multiplying scaling factor to max ratio, we can easily keep the max/min ratios in terms of ratios and not fractions. For example: if the max ratio = 36 cpuinfo.max_freq = 36 * 100000 = 3600000 Suppose user space sets a limit of 1200000, then we can calculate max ratio limit as = 36 * 1200000 / 3600000 = 12 This will be correct for any user limits. The other advantage is that, we don't need to do any calculation in the fast path as ratio limit is already calculated via set_policy() callback. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 51204e0 commit 1a4fe38

File tree

1 file changed

+63
-51
lines changed

1 file changed

+63
-51
lines changed

drivers/cpufreq/intel_pstate.c

Lines changed: 63 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,8 @@ struct global_params {
231231
* @prev_cummulative_iowait: IO Wait time difference from last and
232232
* current sample
233233
* @sample: Storage for storing last Sample data
234-
* @min_perf: Minimum capacity limit as a fraction of the maximum
235-
* turbo P-state capacity.
236-
* @max_perf: Maximum capacity limit as a fraction of the maximum
237-
* turbo P-state capacity.
234+
* @min_perf_ratio: Minimum capacity in terms of PERF or HWP ratios
235+
* @max_perf_ratio: Maximum capacity in terms of PERF or HWP ratios
238236
* @acpi_perf_data: Stores ACPI perf information read from _PSS
239237
* @valid_pss_table: Set to true for valid ACPI _PSS entries found
240238
* @epp_powersave: Last saved HWP energy performance preference
@@ -266,8 +264,8 @@ struct cpudata {
266264
u64 prev_tsc;
267265
u64 prev_cummulative_iowait;
268266
struct sample sample;
269-
int32_t min_perf;
270-
int32_t max_perf;
267+
int32_t min_perf_ratio;
268+
int32_t max_perf_ratio;
271269
#ifdef CONFIG_ACPI
272270
struct acpi_processor_performance acpi_perf_data;
273271
bool valid_pss_table;
@@ -794,25 +792,32 @@ static struct freq_attr *hwp_cpufreq_attrs[] = {
794792
NULL,
795793
};
796794

797-
static void intel_pstate_hwp_set(unsigned int cpu)
795+
static void intel_pstate_get_hwp_max(unsigned int cpu, int *phy_max,
796+
int *current_max)
798797
{
799-
struct cpudata *cpu_data = all_cpu_data[cpu];
800-
int min, hw_min, max, hw_max;
801-
u64 value, cap;
802-
s16 epp;
798+
u64 cap;
803799

804800
rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap);
805-
hw_min = HWP_LOWEST_PERF(cap);
806801
if (global.no_turbo)
807-
hw_max = HWP_GUARANTEED_PERF(cap);
802+
*current_max = HWP_GUARANTEED_PERF(cap);
808803
else
809-
hw_max = HWP_HIGHEST_PERF(cap);
804+
*current_max = HWP_HIGHEST_PERF(cap);
805+
806+
*phy_max = HWP_HIGHEST_PERF(cap);
807+
}
808+
809+
static void intel_pstate_hwp_set(unsigned int cpu)
810+
{
811+
struct cpudata *cpu_data = all_cpu_data[cpu];
812+
int max, min;
813+
u64 value;
814+
s16 epp;
815+
816+
max = cpu_data->max_perf_ratio;
817+
min = cpu_data->min_perf_ratio;
810818

811-
max = fp_ext_toint(hw_max * cpu_data->max_perf);
812819
if (cpu_data->policy == CPUFREQ_POLICY_PERFORMANCE)
813820
min = max;
814-
else
815-
min = fp_ext_toint(hw_max * cpu_data->min_perf);
816821

817822
rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value);
818823

@@ -1528,8 +1533,7 @@ static void intel_pstate_max_within_limits(struct cpudata *cpu)
15281533

15291534
update_turbo_state();
15301535
pstate = intel_pstate_get_base_pstate(cpu);
1531-
pstate = max(cpu->pstate.min_pstate,
1532-
fp_ext_toint(pstate * cpu->max_perf));
1536+
pstate = max(cpu->pstate.min_pstate, cpu->max_perf_ratio);
15331537
intel_pstate_set_pstate(cpu, pstate);
15341538
}
15351539

@@ -1695,9 +1699,8 @@ static int intel_pstate_prepare_request(struct cpudata *cpu, int pstate)
16951699
int max_pstate = intel_pstate_get_base_pstate(cpu);
16961700
int min_pstate;
16971701

1698-
min_pstate = max(cpu->pstate.min_pstate,
1699-
fp_ext_toint(max_pstate * cpu->min_perf));
1700-
max_pstate = max(min_pstate, fp_ext_toint(max_pstate * cpu->max_perf));
1702+
min_pstate = max(cpu->pstate.min_pstate, cpu->min_perf_ratio);
1703+
max_pstate = max(min_pstate, cpu->max_perf_ratio);
17011704
return clamp_t(int, pstate, min_pstate, max_pstate);
17021705
}
17031706

@@ -1967,52 +1970,61 @@ static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
19671970
{
19681971
int max_freq = intel_pstate_get_max_freq(cpu);
19691972
int32_t max_policy_perf, min_policy_perf;
1973+
int max_state, turbo_max;
19701974

1971-
max_policy_perf = div_ext_fp(policy->max, max_freq);
1972-
max_policy_perf = clamp_t(int32_t, max_policy_perf, 0, int_ext_tofp(1));
1975+
/*
1976+
* HWP needs some special consideration, because on BDX the
1977+
* HWP_REQUEST uses abstract value to represent performance
1978+
* rather than pure ratios.
1979+
*/
1980+
if (hwp_active) {
1981+
intel_pstate_get_hwp_max(cpu->cpu, &turbo_max, &max_state);
1982+
} else {
1983+
max_state = intel_pstate_get_base_pstate(cpu);
1984+
turbo_max = cpu->pstate.turbo_pstate;
1985+
}
1986+
1987+
max_policy_perf = max_state * policy->max / max_freq;
19731988
if (policy->max == policy->min) {
19741989
min_policy_perf = max_policy_perf;
19751990
} else {
1976-
min_policy_perf = div_ext_fp(policy->min, max_freq);
1991+
min_policy_perf = max_state * policy->min / max_freq;
19771992
min_policy_perf = clamp_t(int32_t, min_policy_perf,
19781993
0, max_policy_perf);
19791994
}
19801995

1996+
pr_debug("cpu:%d max_state %d min_policy_perf:%d max_policy_perf:%d\n",
1997+
policy->cpu, max_state,
1998+
min_policy_perf, max_policy_perf);
1999+
19812000
/* Normalize user input to [min_perf, max_perf] */
19822001
if (per_cpu_limits) {
1983-
cpu->min_perf = min_policy_perf;
1984-
cpu->max_perf = max_policy_perf;
2002+
cpu->min_perf_ratio = min_policy_perf;
2003+
cpu->max_perf_ratio = max_policy_perf;
19852004
} else {
19862005
int32_t global_min, global_max;
19872006

19882007
/* Global limits are in percent of the maximum turbo P-state. */
1989-
global_max = percent_ext_fp(global.max_perf_pct);
1990-
global_min = percent_ext_fp(global.min_perf_pct);
1991-
if (max_freq != cpu->pstate.turbo_freq) {
1992-
int32_t turbo_factor;
1993-
1994-
turbo_factor = div_ext_fp(cpu->pstate.turbo_pstate,
1995-
cpu->pstate.max_pstate);
1996-
global_min = mul_ext_fp(global_min, turbo_factor);
1997-
global_max = mul_ext_fp(global_max, turbo_factor);
1998-
}
2008+
global_max = DIV_ROUND_UP(turbo_max * global.max_perf_pct, 100);
2009+
global_min = DIV_ROUND_UP(turbo_max * global.min_perf_pct, 100);
19992010
global_min = clamp_t(int32_t, global_min, 0, global_max);
20002011

2001-
cpu->min_perf = max(min_policy_perf, global_min);
2002-
cpu->min_perf = min(cpu->min_perf, max_policy_perf);
2003-
cpu->max_perf = min(max_policy_perf, global_max);
2004-
cpu->max_perf = max(min_policy_perf, cpu->max_perf);
2012+
pr_debug("cpu:%d global_min:%d global_max:%d\n", policy->cpu,
2013+
global_min, global_max);
20052014

2006-
/* Make sure min_perf <= max_perf */
2007-
cpu->min_perf = min(cpu->min_perf, cpu->max_perf);
2008-
}
2015+
cpu->min_perf_ratio = max(min_policy_perf, global_min);
2016+
cpu->min_perf_ratio = min(cpu->min_perf_ratio, max_policy_perf);
2017+
cpu->max_perf_ratio = min(max_policy_perf, global_max);
2018+
cpu->max_perf_ratio = max(min_policy_perf, cpu->max_perf_ratio);
20092019

2010-
cpu->max_perf = round_up(cpu->max_perf, EXT_FRAC_BITS);
2011-
cpu->min_perf = round_up(cpu->min_perf, EXT_FRAC_BITS);
2020+
/* Make sure min_perf <= max_perf */
2021+
cpu->min_perf_ratio = min(cpu->min_perf_ratio,
2022+
cpu->max_perf_ratio);
20122023

2013-
pr_debug("cpu:%d max_perf_pct:%d min_perf_pct:%d\n", policy->cpu,
2014-
fp_ext_toint(cpu->max_perf * 100),
2015-
fp_ext_toint(cpu->min_perf * 100));
2024+
}
2025+
pr_debug("cpu:%d max_perf_ratio:%d min_perf_ratio:%d\n", policy->cpu,
2026+
cpu->max_perf_ratio,
2027+
cpu->min_perf_ratio);
20162028
}
20172029

20182030
static int intel_pstate_set_policy(struct cpufreq_policy *policy)
@@ -2115,8 +2127,8 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
21152127

21162128
cpu = all_cpu_data[policy->cpu];
21172129

2118-
cpu->max_perf = int_ext_tofp(1);
2119-
cpu->min_perf = 0;
2130+
cpu->max_perf_ratio = 0xFF;
2131+
cpu->min_perf_ratio = 0;
21202132

21212133
policy->min = cpu->pstate.min_pstate * cpu->pstate.scaling;
21222134
policy->max = cpu->pstate.turbo_pstate * cpu->pstate.scaling;

0 commit comments

Comments
 (0)