aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-03-26 07:19:52 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-04-08 05:26:09 -0400
commit9083e4986124389e2a7c0ffca95630a4983887f0 (patch)
tree8025aa0b9e8d68f10fccc83c1102870493ff7ff1
parent9eca544b1491df90ea7102a7ed14acc3c562d97b (diff)
cpufreq: intel_pstate: Update max frequency on global turbo changes
While the cpuinfo.max_freq value doesn't really matter for intel_pstate in the active mode, in the passive mode it is used by governors as the maximum physical frequency of the CPU and the results of governor computations generally depend on it. Also it is made available to user space via sysfs and it should match the current HW configuration. For this reason, make intel_pstate update cpuinfo.max_freq for all CPUs if it detects a global change of turbo frequency settings from "disable" to "enable" or the other way associated with a _PPC change notification from the platform firmware. Note that policy_is_inactive(), cpufreq_cpu_acquire(), cpufreq_cpu_release(), and cpufreq_set_policy() need to be made available to it for this purpose. Link: https://bugzilla.kernel.org/show_bug.cgi?id=200759 Reported-by: Gabriele Mazzotta <gabriele.mzt@gmail.com> Tested-by: Gabriele Mazzotta <gabriele.mzt@gmail.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--drivers/cpufreq/cpufreq.c16
-rw-r--r--drivers/cpufreq/intel_pstate.c35
-rw-r--r--include/linux/cpufreq.h10
3 files changed, 43 insertions, 18 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index d8fc395af773..f3f79266ab48 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -34,11 +34,6 @@
34 34
35static LIST_HEAD(cpufreq_policy_list); 35static LIST_HEAD(cpufreq_policy_list);
36 36
37static inline bool policy_is_inactive(struct cpufreq_policy *policy)
38{
39 return cpumask_empty(policy->cpus);
40}
41
42/* Macros to iterate over CPU policies */ 37/* Macros to iterate over CPU policies */
43#define for_each_suitable_policy(__policy, __active) \ 38#define for_each_suitable_policy(__policy, __active) \
44 list_for_each_entry(__policy, &cpufreq_policy_list, policy_list) \ 39 list_for_each_entry(__policy, &cpufreq_policy_list, policy_list) \
@@ -254,7 +249,7 @@ EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
254 * cpufreq_cpu_release - Unlock a policy and decrement its usage counter. 249 * cpufreq_cpu_release - Unlock a policy and decrement its usage counter.
255 * @policy: cpufreq policy returned by cpufreq_cpu_acquire(). 250 * @policy: cpufreq policy returned by cpufreq_cpu_acquire().
256 */ 251 */
257static void cpufreq_cpu_release(struct cpufreq_policy *policy) 252void cpufreq_cpu_release(struct cpufreq_policy *policy)
258{ 253{
259 if (WARN_ON(!policy)) 254 if (WARN_ON(!policy))
260 return; 255 return;
@@ -278,7 +273,7 @@ static void cpufreq_cpu_release(struct cpufreq_policy *policy)
278 * cpufreq_cpu_release() in order to release its rwsem and balance its usage 273 * cpufreq_cpu_release() in order to release its rwsem and balance its usage
279 * counter properly. 274 * counter properly.
280 */ 275 */
281static struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu) 276struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu)
282{ 277{
283 struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 278 struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
284 279
@@ -714,9 +709,6 @@ static ssize_t show_scaling_cur_freq(struct cpufreq_policy *policy, char *buf)
714 return ret; 709 return ret;
715} 710}
716 711
717static int cpufreq_set_policy(struct cpufreq_policy *policy,
718 struct cpufreq_policy *new_policy);
719
720/** 712/**
721 * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access 713 * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
722 */ 714 */
@@ -2274,8 +2266,8 @@ EXPORT_SYMBOL(cpufreq_get_policy);
2274 * 2266 *
2275 * The cpuinfo part of @policy is not updated by this function. 2267 * The cpuinfo part of @policy is not updated by this function.
2276 */ 2268 */
2277static int cpufreq_set_policy(struct cpufreq_policy *policy, 2269int cpufreq_set_policy(struct cpufreq_policy *policy,
2278 struct cpufreq_policy *new_policy) 2270 struct cpufreq_policy *new_policy)
2279{ 2271{
2280 struct cpufreq_governor *old_gov; 2272 struct cpufreq_governor *old_gov;
2281 int ret; 2273 int ret;
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index e2191a570ade..08d1a1e845aa 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -179,7 +179,7 @@ struct vid_data {
179 * based on the MSR_IA32_MISC_ENABLE value and whether or 179 * based on the MSR_IA32_MISC_ENABLE value and whether or
180 * not the maximum reported turbo P-state is different from 180 * not the maximum reported turbo P-state is different from
181 * the maximum reported non-turbo one. 181 * the maximum reported non-turbo one.
182 * @turbo_disabled_s: Saved @turbo_disabled value. 182 * @turbo_disabled_mf: The @turbo_disabled value reflected by cpuinfo.max_freq.
183 * @min_perf_pct: Minimum capacity limit in percent of the maximum turbo 183 * @min_perf_pct: Minimum capacity limit in percent of the maximum turbo
184 * P-state capacity. 184 * P-state capacity.
185 * @max_perf_pct: Maximum capacity limit in percent of the maximum turbo 185 * @max_perf_pct: Maximum capacity limit in percent of the maximum turbo
@@ -188,7 +188,7 @@ struct vid_data {
188struct global_params { 188struct global_params {
189 bool no_turbo; 189 bool no_turbo;
190 bool turbo_disabled; 190 bool turbo_disabled;
191 bool turbo_disabled_s; 191 bool turbo_disabled_mf;
192 int max_perf_pct; 192 int max_perf_pct;
193 int min_perf_pct; 193 int min_perf_pct;
194}; 194};
@@ -899,6 +899,28 @@ static void intel_pstate_update_policies(void)
899 cpufreq_update_policy(cpu); 899 cpufreq_update_policy(cpu);
900} 900}
901 901
902static void intel_pstate_update_max_freq(unsigned int cpu)
903{
904 struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu);
905 struct cpufreq_policy new_policy;
906 struct cpudata *cpudata;
907
908 if (!policy)
909 return;
910
911 cpudata = all_cpu_data[cpu];
912 policy->cpuinfo.max_freq = global.turbo_disabled_mf ?
913 cpudata->pstate.max_freq : cpudata->pstate.turbo_freq;
914
915 memcpy(&new_policy, policy, sizeof(*policy));
916 new_policy.max = min(policy->user_policy.max, policy->cpuinfo.max_freq);
917 new_policy.min = min(policy->user_policy.min, new_policy.max);
918
919 cpufreq_set_policy(policy, &new_policy);
920
921 cpufreq_cpu_release(policy);
922}
923
902static void intel_pstate_update_limits(unsigned int cpu) 924static void intel_pstate_update_limits(unsigned int cpu)
903{ 925{
904 mutex_lock(&intel_pstate_driver_lock); 926 mutex_lock(&intel_pstate_driver_lock);
@@ -908,9 +930,10 @@ static void intel_pstate_update_limits(unsigned int cpu)
908 * If turbo has been turned on or off globally, policy limits for 930 * If turbo has been turned on or off globally, policy limits for
909 * all CPUs need to be updated to reflect that. 931 * all CPUs need to be updated to reflect that.
910 */ 932 */
911 if (global.turbo_disabled_s != global.turbo_disabled) { 933 if (global.turbo_disabled_mf != global.turbo_disabled) {
912 global.turbo_disabled_s = global.turbo_disabled; 934 global.turbo_disabled_mf = global.turbo_disabled;
913 intel_pstate_update_policies(); 935 for_each_possible_cpu(cpu)
936 intel_pstate_update_max_freq(cpu);
914 } else { 937 } else {
915 cpufreq_update_policy(cpu); 938 cpufreq_update_policy(cpu);
916 } 939 }
@@ -2159,7 +2182,7 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
2159 /* cpuinfo and default policy values */ 2182 /* cpuinfo and default policy values */
2160 policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling; 2183 policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling;
2161 update_turbo_state(); 2184 update_turbo_state();
2162 global.turbo_disabled_s = global.turbo_disabled; 2185 global.turbo_disabled_mf = global.turbo_disabled;
2163 policy->cpuinfo.max_freq = global.turbo_disabled ? 2186 policy->cpuinfo.max_freq = global.turbo_disabled ?
2164 cpu->pstate.max_pstate : cpu->pstate.turbo_pstate; 2187 cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
2165 policy->cpuinfo.max_freq *= cpu->pstate.scaling; 2188 policy->cpuinfo.max_freq *= cpu->pstate.scaling;
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 5005ea40364f..684caf067003 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -178,6 +178,11 @@ static inline struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
178static inline void cpufreq_cpu_put(struct cpufreq_policy *policy) { } 178static inline void cpufreq_cpu_put(struct cpufreq_policy *policy) { }
179#endif 179#endif
180 180
181static inline bool policy_is_inactive(struct cpufreq_policy *policy)
182{
183 return cpumask_empty(policy->cpus);
184}
185
181static inline bool policy_is_shared(struct cpufreq_policy *policy) 186static inline bool policy_is_shared(struct cpufreq_policy *policy)
182{ 187{
183 return cpumask_weight(policy->cpus) > 1; 188 return cpumask_weight(policy->cpus) > 1;
@@ -193,7 +198,12 @@ unsigned int cpufreq_quick_get_max(unsigned int cpu);
193void disable_cpufreq(void); 198void disable_cpufreq(void);
194 199
195u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy); 200u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy);
201
202struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu);
203void cpufreq_cpu_release(struct cpufreq_policy *policy);
196int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); 204int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
205int cpufreq_set_policy(struct cpufreq_policy *policy,
206 struct cpufreq_policy *new_policy);
197void cpufreq_update_policy(unsigned int cpu); 207void cpufreq_update_policy(unsigned int cpu);
198void cpufreq_update_limits(unsigned int cpu); 208void cpufreq_update_limits(unsigned int cpu);
199bool have_governor_per_policy(void); 209bool have_governor_per_policy(void);