diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-03-31 11:42:15 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-03-31 11:42:15 -0400 |
commit | bb6ab52f2befe1fb29ac198f27d8a6aadf510f81 (patch) | |
tree | e1fd997a070d0a2f53e0be2a520d4287befb898c | |
parent | 539a4c4247c2697d291a8fb02c485ccd7cf34f05 (diff) |
intel_pstate: Do not set utilization update hook too early
The utilization update hook in the intel_pstate driver is set too
early, as it only should be set after the policy has been fully
initialized by the core. That may cause intel_pstate_update_util()
to use incorrect data and put the CPUs into incorrect P-states as
a result.
To prevent that from happening, make intel_pstate_set_policy() set
the utilization update hook instead of intel_pstate_init_cpu() so
intel_pstate_update_util() only runs when all things have been
initialized as appropriate.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 4b644526fd59..81057e48c4de 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -1103,7 +1103,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum) | |||
1103 | intel_pstate_sample(cpu, 0); | 1103 | intel_pstate_sample(cpu, 0); |
1104 | 1104 | ||
1105 | cpu->update_util.func = intel_pstate_update_util; | 1105 | cpu->update_util.func = intel_pstate_update_util; |
1106 | cpufreq_set_update_util_data(cpunum, &cpu->update_util); | ||
1107 | 1106 | ||
1108 | pr_debug("intel_pstate: controlling: cpu %d\n", cpunum); | 1107 | pr_debug("intel_pstate: controlling: cpu %d\n", cpunum); |
1109 | 1108 | ||
@@ -1122,18 +1121,29 @@ static unsigned int intel_pstate_get(unsigned int cpu_num) | |||
1122 | return get_avg_frequency(cpu); | 1121 | return get_avg_frequency(cpu); |
1123 | } | 1122 | } |
1124 | 1123 | ||
1124 | static void intel_pstate_set_update_util_hook(unsigned int cpu) | ||
1125 | { | ||
1126 | cpufreq_set_update_util_data(cpu, &all_cpu_data[cpu]->update_util); | ||
1127 | } | ||
1128 | |||
1129 | static void intel_pstate_clear_update_util_hook(unsigned int cpu) | ||
1130 | { | ||
1131 | cpufreq_set_update_util_data(cpu, NULL); | ||
1132 | synchronize_sched(); | ||
1133 | } | ||
1134 | |||
1125 | static int intel_pstate_set_policy(struct cpufreq_policy *policy) | 1135 | static int intel_pstate_set_policy(struct cpufreq_policy *policy) |
1126 | { | 1136 | { |
1127 | if (!policy->cpuinfo.max_freq) | 1137 | if (!policy->cpuinfo.max_freq) |
1128 | return -ENODEV; | 1138 | return -ENODEV; |
1129 | 1139 | ||
1140 | intel_pstate_clear_update_util_hook(policy->cpu); | ||
1141 | |||
1130 | if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && | 1142 | if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && |
1131 | policy->max >= policy->cpuinfo.max_freq) { | 1143 | policy->max >= policy->cpuinfo.max_freq) { |
1132 | pr_debug("intel_pstate: set performance\n"); | 1144 | pr_debug("intel_pstate: set performance\n"); |
1133 | limits = &performance_limits; | 1145 | limits = &performance_limits; |
1134 | if (hwp_active) | 1146 | goto out; |
1135 | intel_pstate_hwp_set(policy->cpus); | ||
1136 | return 0; | ||
1137 | } | 1147 | } |
1138 | 1148 | ||
1139 | pr_debug("intel_pstate: set powersave\n"); | 1149 | pr_debug("intel_pstate: set powersave\n"); |
@@ -1163,6 +1173,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
1163 | limits->max_perf = div_fp(int_tofp(limits->max_perf_pct), | 1173 | limits->max_perf = div_fp(int_tofp(limits->max_perf_pct), |
1164 | int_tofp(100)); | 1174 | int_tofp(100)); |
1165 | 1175 | ||
1176 | out: | ||
1177 | intel_pstate_set_update_util_hook(policy->cpu); | ||
1178 | |||
1166 | if (hwp_active) | 1179 | if (hwp_active) |
1167 | intel_pstate_hwp_set(policy->cpus); | 1180 | intel_pstate_hwp_set(policy->cpus); |
1168 | 1181 | ||
@@ -1187,8 +1200,7 @@ static void intel_pstate_stop_cpu(struct cpufreq_policy *policy) | |||
1187 | 1200 | ||
1188 | pr_debug("intel_pstate: CPU %d exiting\n", cpu_num); | 1201 | pr_debug("intel_pstate: CPU %d exiting\n", cpu_num); |
1189 | 1202 | ||
1190 | cpufreq_set_update_util_data(cpu_num, NULL); | 1203 | intel_pstate_clear_update_util_hook(cpu_num); |
1191 | synchronize_sched(); | ||
1192 | 1204 | ||
1193 | if (hwp_active) | 1205 | if (hwp_active) |
1194 | return; | 1206 | return; |
@@ -1455,8 +1467,7 @@ out: | |||
1455 | get_online_cpus(); | 1467 | get_online_cpus(); |
1456 | for_each_online_cpu(cpu) { | 1468 | for_each_online_cpu(cpu) { |
1457 | if (all_cpu_data[cpu]) { | 1469 | if (all_cpu_data[cpu]) { |
1458 | cpufreq_set_update_util_data(cpu, NULL); | 1470 | intel_pstate_clear_update_util_hook(cpu); |
1459 | synchronize_sched(); | ||
1460 | kfree(all_cpu_data[cpu]); | 1471 | kfree(all_cpu_data[cpu]); |
1461 | } | 1472 | } |
1462 | } | 1473 | } |