aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-02-28 18:07:36 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-03-05 18:06:04 -0500
commitcd59b4bed9d11a2aefc4bb44eed9de0e6c1eea06 (patch)
tree9f19cdab11c4ec57352032fd9ac8818405d745f5
parentd82f26925599cae83c38d17d07ae982356e81318 (diff)
cpufreq: intel_pstate: Fix global settings in active mode
Commit 111b8b3fe4fa (cpufreq: intel_pstate: Always keep all limits settings in sync) changed intel_pstate to invoke cpufreq_update_policy() for every registered CPU on global sysfs attributes updates, but that led to undesirable effects in the active mode if the "performance" P-state selection algorithm is configufred for one CPU and the "powersave" one is chosen for all of the other CPUs. Namely, in that case, the following is possible: # cd /sys/devices/system/cpu/ # cat intel_pstate/max_perf_pct 100 # cat intel_pstate/min_perf_pct 26 # echo performance > cpufreq/policy0/scaling_governor # cat intel_pstate/max_perf_pct 100 # cat intel_pstate/min_perf_pct 100 # echo 94 > intel_pstate/min_perf_pct # cat intel_pstate/min_perf_pct 26 The reason why this happens is because intel_pstate attempts to maintain two sets of global limits in the active mode, one for the "performance" P-state selection algorithm and one for the "powersave" P-state selection algorithm, but the P-state selection algorithms are set per policy, so the global limits cannot reflect all of them at the same time if they are different for different policies. In the particular situation above, the attempt to change min_perf_pct to 94 caused cpufreq_update_policy() to be run for a CPU with the "powersave" P-state selection algorithm and intel_pstate_set_policy() called by it silently switched the global limits to the "powersave" set which finally was reflected by the sysfs interface. To prevent that from happening, modify intel_pstate_update_policies() to always switch back to the set of limits that was used right before it has been invoked. Fixes: 111b8b3fe4fa (cpufreq: intel_pstate: Always keep all limits settings in sync) Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/cpufreq/intel_pstate.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 5e066b332598..436a4c5ba70d 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -973,11 +973,20 @@ static int intel_pstate_resume(struct cpufreq_policy *policy)
973} 973}
974 974
975static void intel_pstate_update_policies(void) 975static void intel_pstate_update_policies(void)
976 __releases(&intel_pstate_limits_lock)
977 __acquires(&intel_pstate_limits_lock)
976{ 978{
979 struct perf_limits *saved_limits = limits;
977 int cpu; 980 int cpu;
978 981
982 mutex_unlock(&intel_pstate_limits_lock);
983
979 for_each_possible_cpu(cpu) 984 for_each_possible_cpu(cpu)
980 cpufreq_update_policy(cpu); 985 cpufreq_update_policy(cpu);
986
987 mutex_lock(&intel_pstate_limits_lock);
988
989 limits = saved_limits;
981} 990}
982 991
983/************************** debugfs begin ************************/ 992/************************** debugfs begin ************************/
@@ -1185,10 +1194,10 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
1185 1194
1186 limits->no_turbo = clamp_t(int, input, 0, 1); 1195 limits->no_turbo = clamp_t(int, input, 0, 1);
1187 1196
1188 mutex_unlock(&intel_pstate_limits_lock);
1189
1190 intel_pstate_update_policies(); 1197 intel_pstate_update_policies();
1191 1198
1199 mutex_unlock(&intel_pstate_limits_lock);
1200
1192 mutex_unlock(&intel_pstate_driver_lock); 1201 mutex_unlock(&intel_pstate_driver_lock);
1193 1202
1194 return count; 1203 return count;
@@ -1222,10 +1231,10 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
1222 limits->max_perf_pct); 1231 limits->max_perf_pct);
1223 limits->max_perf = div_ext_fp(limits->max_perf_pct, 100); 1232 limits->max_perf = div_ext_fp(limits->max_perf_pct, 100);
1224 1233
1225 mutex_unlock(&intel_pstate_limits_lock);
1226
1227 intel_pstate_update_policies(); 1234 intel_pstate_update_policies();
1228 1235
1236 mutex_unlock(&intel_pstate_limits_lock);
1237
1229 mutex_unlock(&intel_pstate_driver_lock); 1238 mutex_unlock(&intel_pstate_driver_lock);
1230 1239
1231 return count; 1240 return count;
@@ -1259,10 +1268,10 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
1259 limits->min_perf_pct); 1268 limits->min_perf_pct);
1260 limits->min_perf = div_ext_fp(limits->min_perf_pct, 100); 1269 limits->min_perf = div_ext_fp(limits->min_perf_pct, 100);
1261 1270
1262 mutex_unlock(&intel_pstate_limits_lock);
1263
1264 intel_pstate_update_policies(); 1271 intel_pstate_update_policies();
1265 1272
1273 mutex_unlock(&intel_pstate_limits_lock);
1274
1266 mutex_unlock(&intel_pstate_driver_lock); 1275 mutex_unlock(&intel_pstate_driver_lock);
1267 1276
1268 return count; 1277 return count;