aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-03-22 19:00:47 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-03-23 22:04:32 -0400
commit80b120ca1a75c2df093d15936ab0591d90c99de9 (patch)
treee90a305d114dc1efbc5bf197e958f94bb735208d
parentc5a2ee7dde893e0a06044e75c16711f08d5c011d (diff)
cpufreq: intel_pstate: Avoid transient updates of cpuinfo.max_freq
Both intel_pstate_verify_policy() and intel_cpufreq_verify_policy() set policy->cpuinfo.max_freq depending on the turbo status, but the updates made by them are discarded by the core, because the policy object passed to them by the core is temporary and cpuinfo.max_freq from that object is not copied to the final policy object in cpufreq_set_policy(). However, cpufreq_set_policy() passes the temporary policy object to the ->setpolicy callback of the driver, so intel_pstate_set_policy() actually sees the policy->cpuinfo.max_freq value updated by intel_pstate_verify_policy() and not the final one. It also updates policy->max sometimes which basically has no effect after it returns, because the core discards that update. To avoid confusion, eliminate policy->cpuinfo.max_freq updates from intel_pstate_verify_policy() and intel_cpufreq_verify_policy() entirely and check the maximum frequency explicitly in intel_pstate_update_perf_limits() instead of relying on the transiently updated policy->cpuinfo.max_freq value. Moreover, move the max->policy adjustment carried out in intel_pstate_set_policy() to a separate function and call that function from the ->verify driver callbacks to ensure that it will actually be effective. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/cpufreq/intel_pstate.c47
1 files changed, 28 insertions, 19 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index c0afa78624a1..60544c210d75 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -2021,19 +2021,25 @@ static void intel_pstate_clear_update_util_hook(unsigned int cpu)
2021 synchronize_sched(); 2021 synchronize_sched();
2022} 2022}
2023 2023
2024static int intel_pstate_get_max_freq(struct cpudata *cpu)
2025{
2026 return global.turbo_disabled || global.no_turbo ?
2027 cpu->pstate.max_freq : cpu->pstate.turbo_freq;
2028}
2029
2024static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy, 2030static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
2025 struct cpudata *cpu) 2031 struct cpudata *cpu)
2026{ 2032{
2027 struct perf_limits *limits = &cpu->perf_limits; 2033 struct perf_limits *limits = &cpu->perf_limits;
2034 int max_freq = intel_pstate_get_max_freq(cpu);
2028 int32_t max_policy_perf, min_policy_perf; 2035 int32_t max_policy_perf, min_policy_perf;
2029 2036
2030 max_policy_perf = div_ext_fp(policy->max, policy->cpuinfo.max_freq); 2037 max_policy_perf = div_ext_fp(policy->max, max_freq);
2031 max_policy_perf = clamp_t(int32_t, max_policy_perf, 0, int_ext_tofp(1)); 2038 max_policy_perf = clamp_t(int32_t, max_policy_perf, 0, int_ext_tofp(1));
2032 if (policy->max == policy->min) { 2039 if (policy->max == policy->min) {
2033 min_policy_perf = max_policy_perf; 2040 min_policy_perf = max_policy_perf;
2034 } else { 2041 } else {
2035 min_policy_perf = div_ext_fp(policy->min, 2042 min_policy_perf = div_ext_fp(policy->min, max_freq);
2036 policy->cpuinfo.max_freq);
2037 min_policy_perf = clamp_t(int32_t, min_policy_perf, 2043 min_policy_perf = clamp_t(int32_t, min_policy_perf,
2038 0, max_policy_perf); 2044 0, max_policy_perf);
2039 } 2045 }
@@ -2048,7 +2054,7 @@ static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
2048 /* Global limits are in percent of the maximum turbo P-state. */ 2054 /* Global limits are in percent of the maximum turbo P-state. */
2049 global_max = percent_ext_fp(global.max_perf_pct); 2055 global_max = percent_ext_fp(global.max_perf_pct);
2050 global_min = percent_ext_fp(global.min_perf_pct); 2056 global_min = percent_ext_fp(global.min_perf_pct);
2051 if (policy->cpuinfo.max_freq != cpu->pstate.turbo_freq) { 2057 if (max_freq != cpu->pstate.turbo_freq) {
2052 int32_t turbo_factor; 2058 int32_t turbo_factor;
2053 2059
2054 turbo_factor = div_ext_fp(cpu->pstate.turbo_pstate, 2060 turbo_factor = div_ext_fp(cpu->pstate.turbo_pstate,
@@ -2088,13 +2094,6 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
2088 cpu = all_cpu_data[policy->cpu]; 2094 cpu = all_cpu_data[policy->cpu];
2089 cpu->policy = policy->policy; 2095 cpu->policy = policy->policy;
2090 2096
2091 if (cpu->pstate.max_pstate_physical > cpu->pstate.max_pstate &&
2092 policy->max < policy->cpuinfo.max_freq &&
2093 policy->max > cpu->pstate.max_pstate * cpu->pstate.scaling) {
2094 pr_debug("policy->max > max non turbo frequency\n");
2095 policy->max = policy->cpuinfo.max_freq;
2096 }
2097
2098 mutex_lock(&intel_pstate_limits_lock); 2097 mutex_lock(&intel_pstate_limits_lock);
2099 2098
2100 intel_pstate_update_perf_limits(policy, cpu); 2099 intel_pstate_update_perf_limits(policy, cpu);
@@ -2118,21 +2117,31 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
2118 return 0; 2117 return 0;
2119} 2118}
2120 2119
2120static void intel_pstate_adjust_policy_max(struct cpufreq_policy *policy,
2121 struct cpudata *cpu)
2122{
2123 if (cpu->pstate.max_pstate_physical > cpu->pstate.max_pstate &&
2124 policy->max < policy->cpuinfo.max_freq &&
2125 policy->max > cpu->pstate.max_freq) {
2126 pr_debug("policy->max > max non turbo frequency\n");
2127 policy->max = policy->cpuinfo.max_freq;
2128 }
2129}
2130
2121static int intel_pstate_verify_policy(struct cpufreq_policy *policy) 2131static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
2122{ 2132{
2123 struct cpudata *cpu = all_cpu_data[policy->cpu]; 2133 struct cpudata *cpu = all_cpu_data[policy->cpu];
2124 2134
2125 update_turbo_state(); 2135 update_turbo_state();
2126 policy->cpuinfo.max_freq = global.turbo_disabled || global.no_turbo ? 2136 cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
2127 cpu->pstate.max_freq : 2137 intel_pstate_get_max_freq(cpu));
2128 cpu->pstate.turbo_freq;
2129
2130 cpufreq_verify_within_cpu_limits(policy);
2131 2138
2132 if (policy->policy != CPUFREQ_POLICY_POWERSAVE && 2139 if (policy->policy != CPUFREQ_POLICY_POWERSAVE &&
2133 policy->policy != CPUFREQ_POLICY_PERFORMANCE) 2140 policy->policy != CPUFREQ_POLICY_PERFORMANCE)
2134 return -EINVAL; 2141 return -EINVAL;
2135 2142
2143 intel_pstate_adjust_policy_max(policy, cpu);
2144
2136 return 0; 2145 return 0;
2137} 2146}
2138 2147
@@ -2227,10 +2236,10 @@ static int intel_cpufreq_verify_policy(struct cpufreq_policy *policy)
2227 struct cpudata *cpu = all_cpu_data[policy->cpu]; 2236 struct cpudata *cpu = all_cpu_data[policy->cpu];
2228 2237
2229 update_turbo_state(); 2238 update_turbo_state();
2230 policy->cpuinfo.max_freq = global.no_turbo || global.turbo_disabled ? 2239 cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
2231 cpu->pstate.max_freq : cpu->pstate.turbo_freq; 2240 intel_pstate_get_max_freq(cpu));
2232 2241
2233 cpufreq_verify_within_cpu_limits(policy); 2242 intel_pstate_adjust_policy_max(policy, cpu);
2234 2243
2235 intel_pstate_update_perf_limits(policy, cpu); 2244 intel_pstate_update_perf_limits(policy, cpu);
2236 2245