Skip to content

Commit 7de3255

Browse files
committed
cpufreq: intel_pstate: One set of global limits in active mode
In the active mode intel_pstate currently uses two sets of global limits, each associated with one of the possible scaling_governor settings in that mode: "powersave" or "performance". The driver switches over from one of those sets to the other depending on the scaling_governor setting for the last CPU whose per-policy cpufreq interface in sysfs was last used to change parameters exposed in there. That obviously leads to no end of issues when the scaling_governor settings differ between CPUs. The most recent issue was introduced by commit a240c4a (cpufreq: intel_pstate: Do not reinit performance limits in ->setpolicy) that eliminated the reinitialization of "performance" limits in intel_pstate_set_policy() preventing the max limit from being set to anything below 100, among other things. Namely, an undesirable side effect of commit a240c4a is that now, after setting scaling_governor to "performance" in the active mode, the per-policy limits for the CPU in question go to the highest level and stay there even when it is switched back to "powersave" later. As it turns out, some distributions set scaling_governor to "performance" temporarily for all CPUs to speed-up system initialization, so that change causes them to misbehave later. To fix that, get rid of the performance/powersave global limits split and use just one set of global limits for everything. From the user's persepctive, after this modification, when scaling_governor is switched from "performance" to "powersave" or the other way around on one CPU, the limits settings (ie. the global max/min_perf_pct and per-policy scaling_max/min_freq for any CPUs) will not change. Still, switching from "performance" to "powersave" or the other way around changes the way in which P-states are selected and in particular "performance" causes the driver to always request the highest P-state it is allowed to ask for for the given CPU. Fixes: a240c4a (cpufreq: intel_pstate: Do not reinit performance limits in ->setpolicy) Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent e4c204c commit 7de3255

File tree

1 file changed

+46
-96
lines changed

1 file changed

+46
-96
lines changed

drivers/cpufreq/intel_pstate.c

Lines changed: 46 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,7 @@ static bool driver_registered __read_mostly;
364364
static bool acpi_ppc;
365365
#endif
366366

367-
static struct perf_limits performance_limits;
368-
static struct perf_limits powersave_limits;
369-
static struct perf_limits *limits;
367+
static struct perf_limits global;
370368

371369
static void intel_pstate_init_limits(struct perf_limits *limits)
372370
{
@@ -377,14 +375,6 @@ static void intel_pstate_init_limits(struct perf_limits *limits)
377375
limits->max_sysfs_pct = 100;
378376
}
379377

380-
static void intel_pstate_set_performance_limits(struct perf_limits *limits)
381-
{
382-
intel_pstate_init_limits(limits);
383-
limits->min_perf_pct = 100;
384-
limits->min_perf = int_ext_tofp(1);
385-
limits->min_sysfs_pct = 100;
386-
}
387-
388378
static DEFINE_MUTEX(intel_pstate_driver_lock);
389379
static DEFINE_MUTEX(intel_pstate_limits_lock);
390380

@@ -507,7 +497,7 @@ static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
507497
* correct max turbo frequency based on the turbo state.
508498
* Also need to convert to MHz as _PSS freq is in MHz.
509499
*/
510-
if (!limits->turbo_disabled)
500+
if (!global.turbo_disabled)
511501
cpu->acpi_perf_data.states[0].core_frequency =
512502
policy->cpuinfo.max_freq / 1000;
513503
cpu->valid_pss_table = true;
@@ -626,7 +616,7 @@ static inline void update_turbo_state(void)
626616

627617
cpu = all_cpu_data[0];
628618
rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
629-
limits->turbo_disabled =
619+
global.turbo_disabled =
630620
(misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
631621
cpu->pstate.max_pstate == cpu->pstate.turbo_pstate);
632622
}
@@ -851,7 +841,7 @@ static struct freq_attr *hwp_cpufreq_attrs[] = {
851841
static void intel_pstate_hwp_set(struct cpufreq_policy *policy)
852842
{
853843
int min, hw_min, max, hw_max, cpu;
854-
struct perf_limits *perf_limits = limits;
844+
struct perf_limits *perf_limits = &global;
855845
u64 value, cap;
856846

857847
for_each_cpu(cpu, policy->cpus) {
@@ -863,19 +853,22 @@ static void intel_pstate_hwp_set(struct cpufreq_policy *policy)
863853

864854
rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap);
865855
hw_min = HWP_LOWEST_PERF(cap);
866-
if (limits->no_turbo)
856+
if (global.no_turbo)
867857
hw_max = HWP_GUARANTEED_PERF(cap);
868858
else
869859
hw_max = HWP_HIGHEST_PERF(cap);
870860

871-
min = fp_ext_toint(hw_max * perf_limits->min_perf);
861+
max = fp_ext_toint(hw_max * perf_limits->max_perf);
862+
if (cpu_data->policy == CPUFREQ_POLICY_PERFORMANCE)
863+
min = max;
864+
else
865+
min = fp_ext_toint(hw_max * perf_limits->min_perf);
872866

873867
rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value);
874868

875869
value &= ~HWP_MIN_PERF(~0L);
876870
value |= HWP_MIN_PERF(min);
877871

878-
max = fp_ext_toint(hw_max * perf_limits->max_perf);
879872
value &= ~HWP_MAX_PERF(~0L);
880873
value |= HWP_MAX_PERF(max);
881874

@@ -968,20 +961,11 @@ static int intel_pstate_resume(struct cpufreq_policy *policy)
968961
}
969962

970963
static void intel_pstate_update_policies(void)
971-
__releases(&intel_pstate_limits_lock)
972-
__acquires(&intel_pstate_limits_lock)
973964
{
974-
struct perf_limits *saved_limits = limits;
975965
int cpu;
976966

977-
mutex_unlock(&intel_pstate_limits_lock);
978-
979967
for_each_possible_cpu(cpu)
980968
cpufreq_update_policy(cpu);
981-
982-
mutex_lock(&intel_pstate_limits_lock);
983-
984-
limits = saved_limits;
985969
}
986970

987971
/************************** debugfs begin ************************/
@@ -1060,7 +1044,7 @@ static void intel_pstate_debug_hide_params(void)
10601044
static ssize_t show_##file_name \
10611045
(struct kobject *kobj, struct attribute *attr, char *buf) \
10621046
{ \
1063-
return sprintf(buf, "%u\n", limits->object); \
1047+
return sprintf(buf, "%u\n", global.object); \
10641048
}
10651049

10661050
static ssize_t intel_pstate_show_status(char *buf);
@@ -1151,10 +1135,10 @@ static ssize_t show_no_turbo(struct kobject *kobj,
11511135
}
11521136

11531137
update_turbo_state();
1154-
if (limits->turbo_disabled)
1155-
ret = sprintf(buf, "%u\n", limits->turbo_disabled);
1138+
if (global.turbo_disabled)
1139+
ret = sprintf(buf, "%u\n", global.turbo_disabled);
11561140
else
1157-
ret = sprintf(buf, "%u\n", limits->no_turbo);
1141+
ret = sprintf(buf, "%u\n", global.no_turbo);
11581142

11591143
mutex_unlock(&intel_pstate_driver_lock);
11601144

@@ -1181,19 +1165,19 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
11811165
mutex_lock(&intel_pstate_limits_lock);
11821166

11831167
update_turbo_state();
1184-
if (limits->turbo_disabled) {
1168+
if (global.turbo_disabled) {
11851169
pr_warn("Turbo disabled by BIOS or unavailable on processor\n");
11861170
mutex_unlock(&intel_pstate_limits_lock);
11871171
mutex_unlock(&intel_pstate_driver_lock);
11881172
return -EPERM;
11891173
}
11901174

1191-
limits->no_turbo = clamp_t(int, input, 0, 1);
1192-
1193-
intel_pstate_update_policies();
1175+
global.no_turbo = clamp_t(int, input, 0, 1);
11941176

11951177
mutex_unlock(&intel_pstate_limits_lock);
11961178

1179+
intel_pstate_update_policies();
1180+
11971181
mutex_unlock(&intel_pstate_driver_lock);
11981182

11991183
return count;
@@ -1218,19 +1202,16 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
12181202

12191203
mutex_lock(&intel_pstate_limits_lock);
12201204

1221-
limits->max_sysfs_pct = clamp_t(int, input, 0 , 100);
1222-
limits->max_perf_pct = min(limits->max_policy_pct,
1223-
limits->max_sysfs_pct);
1224-
limits->max_perf_pct = max(limits->min_policy_pct,
1225-
limits->max_perf_pct);
1226-
limits->max_perf_pct = max(limits->min_perf_pct,
1227-
limits->max_perf_pct);
1228-
limits->max_perf = percent_ext_fp(limits->max_perf_pct);
1229-
1230-
intel_pstate_update_policies();
1205+
global.max_sysfs_pct = clamp_t(int, input, 0 , 100);
1206+
global.max_perf_pct = min(global.max_policy_pct, global.max_sysfs_pct);
1207+
global.max_perf_pct = max(global.min_policy_pct, global.max_perf_pct);
1208+
global.max_perf_pct = max(global.min_perf_pct, global.max_perf_pct);
1209+
global.max_perf = percent_ext_fp(global.max_perf_pct);
12311210

12321211
mutex_unlock(&intel_pstate_limits_lock);
12331212

1213+
intel_pstate_update_policies();
1214+
12341215
mutex_unlock(&intel_pstate_driver_lock);
12351216

12361217
return count;
@@ -1255,19 +1236,16 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
12551236

12561237
mutex_lock(&intel_pstate_limits_lock);
12571238

1258-
limits->min_sysfs_pct = clamp_t(int, input, 0 , 100);
1259-
limits->min_perf_pct = max(limits->min_policy_pct,
1260-
limits->min_sysfs_pct);
1261-
limits->min_perf_pct = min(limits->max_policy_pct,
1262-
limits->min_perf_pct);
1263-
limits->min_perf_pct = min(limits->max_perf_pct,
1264-
limits->min_perf_pct);
1265-
limits->min_perf = percent_ext_fp(limits->min_perf_pct);
1266-
1267-
intel_pstate_update_policies();
1239+
global.min_sysfs_pct = clamp_t(int, input, 0 , 100);
1240+
global.min_perf_pct = max(global.min_policy_pct, global.min_sysfs_pct);
1241+
global.min_perf_pct = min(global.max_policy_pct, global.min_perf_pct);
1242+
global.min_perf_pct = min(global.max_perf_pct, global.min_perf_pct);
1243+
global.min_perf = percent_ext_fp(global.min_perf_pct);
12681244

12691245
mutex_unlock(&intel_pstate_limits_lock);
12701246

1247+
intel_pstate_update_policies();
1248+
12711249
mutex_unlock(&intel_pstate_driver_lock);
12721250

12731251
return count;
@@ -1387,7 +1365,7 @@ static u64 atom_get_val(struct cpudata *cpudata, int pstate)
13871365
u32 vid;
13881366

13891367
val = (u64)pstate << 8;
1390-
if (limits->no_turbo && !limits->turbo_disabled)
1368+
if (global.no_turbo && !global.turbo_disabled)
13911369
val |= (u64)1 << 32;
13921370

13931371
vid_fp = cpudata->vid.min + mul_fp(
@@ -1557,7 +1535,7 @@ static u64 core_get_val(struct cpudata *cpudata, int pstate)
15571535
u64 val;
15581536

15591537
val = (u64)pstate << 8;
1560-
if (limits->no_turbo && !limits->turbo_disabled)
1538+
if (global.no_turbo && !global.turbo_disabled)
15611539
val |= (u64)1 << 32;
15621540

15631541
return val;
@@ -1683,9 +1661,9 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
16831661
int max_perf = cpu->pstate.turbo_pstate;
16841662
int max_perf_adj;
16851663
int min_perf;
1686-
struct perf_limits *perf_limits = limits;
1664+
struct perf_limits *perf_limits = &global;
16871665

1688-
if (limits->no_turbo || limits->turbo_disabled)
1666+
if (global.no_turbo || global.turbo_disabled)
16891667
max_perf = cpu->pstate.max_pstate;
16901668

16911669
if (per_cpu_limits)
@@ -1820,7 +1798,7 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
18201798

18211799
sample->busy_scaled = busy_frac * 100;
18221800

1823-
target = limits->no_turbo || limits->turbo_disabled ?
1801+
target = global.no_turbo || global.turbo_disabled ?
18241802
cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
18251803
target += target >> 2;
18261804
target = mul_fp(target, busy_frac);
@@ -2116,7 +2094,7 @@ static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
21162094
static int intel_pstate_set_policy(struct cpufreq_policy *policy)
21172095
{
21182096
struct cpudata *cpu;
2119-
struct perf_limits *perf_limits = NULL;
2097+
struct perf_limits *perf_limits = &global;
21202098

21212099
if (!policy->cpuinfo.max_freq)
21222100
return -ENODEV;
@@ -2139,21 +2117,6 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
21392117

21402118
mutex_lock(&intel_pstate_limits_lock);
21412119

2142-
if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
2143-
pr_debug("set performance\n");
2144-
if (!perf_limits) {
2145-
limits = &performance_limits;
2146-
perf_limits = limits;
2147-
}
2148-
} else {
2149-
pr_debug("set powersave\n");
2150-
if (!perf_limits) {
2151-
limits = &powersave_limits;
2152-
perf_limits = limits;
2153-
}
2154-
2155-
}
2156-
21572120
intel_pstate_update_perf_limits(policy, perf_limits);
21582121

21592122
if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
@@ -2177,16 +2140,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
21772140
static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
21782141
{
21792142
struct cpudata *cpu = all_cpu_data[policy->cpu];
2180-
struct perf_limits *perf_limits;
2181-
2182-
if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
2183-
perf_limits = &performance_limits;
2184-
else
2185-
perf_limits = &powersave_limits;
21862143

21872144
update_turbo_state();
2188-
policy->cpuinfo.max_freq = perf_limits->turbo_disabled ||
2189-
perf_limits->no_turbo ?
2145+
policy->cpuinfo.max_freq = global.turbo_disabled || global.no_turbo ?
21902146
cpu->pstate.max_freq :
21912147
cpu->pstate.turbo_freq;
21922148

@@ -2201,9 +2157,9 @@ static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
22012157
unsigned int max_freq, min_freq;
22022158

22032159
max_freq = policy->cpuinfo.max_freq *
2204-
perf_limits->max_sysfs_pct / 100;
2160+
global.max_sysfs_pct / 100;
22052161
min_freq = policy->cpuinfo.max_freq *
2206-
perf_limits->min_sysfs_pct / 100;
2162+
global.min_sysfs_pct / 100;
22072163
cpufreq_verify_within_limits(policy, min_freq, max_freq);
22082164
}
22092165

@@ -2255,7 +2211,7 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
22552211
/* cpuinfo and default policy values */
22562212
policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling;
22572213
update_turbo_state();
2258-
policy->cpuinfo.max_freq = limits->turbo_disabled ?
2214+
policy->cpuinfo.max_freq = global.turbo_disabled ?
22592215
cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
22602216
policy->cpuinfo.max_freq *= cpu->pstate.scaling;
22612217

@@ -2275,7 +2231,7 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
22752231
return ret;
22762232

22772233
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
2278-
if (limits->min_perf_pct == 100 && limits->max_perf_pct == 100)
2234+
if (IS_ENABLED(CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE))
22792235
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
22802236
else
22812237
policy->policy = CPUFREQ_POLICY_POWERSAVE;
@@ -2301,7 +2257,7 @@ static int intel_cpufreq_verify_policy(struct cpufreq_policy *policy)
23012257
struct cpudata *cpu = all_cpu_data[policy->cpu];
23022258

23032259
update_turbo_state();
2304-
policy->cpuinfo.max_freq = limits->turbo_disabled ?
2260+
policy->cpuinfo.max_freq = global.turbo_disabled ?
23052261
cpu->pstate.max_freq : cpu->pstate.turbo_freq;
23062262

23072263
cpufreq_verify_within_cpu_limits(policy);
@@ -2317,7 +2273,7 @@ static unsigned int intel_cpufreq_turbo_update(struct cpudata *cpu,
23172273

23182274
update_turbo_state();
23192275

2320-
max_freq = limits->no_turbo || limits->turbo_disabled ?
2276+
max_freq = global.no_turbo || global.turbo_disabled ?
23212277
cpu->pstate.max_freq : cpu->pstate.turbo_freq;
23222278
policy->cpuinfo.max_freq = max_freq;
23232279
if (policy->max > max_freq)
@@ -2425,13 +2381,7 @@ static int intel_pstate_register_driver(void)
24252381
{
24262382
int ret;
24272383

2428-
intel_pstate_init_limits(&powersave_limits);
2429-
intel_pstate_set_performance_limits(&performance_limits);
2430-
if (IS_ENABLED(CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE) &&
2431-
intel_pstate_driver == &intel_pstate)
2432-
limits = &performance_limits;
2433-
else
2434-
limits = &powersave_limits;
2384+
intel_pstate_init_limits(&global);
24352385

24362386
ret = cpufreq_register_driver(intel_pstate_driver);
24372387
if (ret) {

0 commit comments

Comments
 (0)