aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-03-26 07:15:13 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-04-01 17:43:05 -0400
commit5a25e3f7cc538fb49e11267c1e41c54ccf83835e (patch)
treee964c1948f3065cc885e0c36fe1b061c3d5ffd45
parent79a3aaa7b82e3106be97842dedfd8429248896e6 (diff)
cpufreq: intel_pstate: Driver-specific handling of _PPC updates
In some cases, the platform firmware disables or enables turbo frequencies for all CPUs globally before triggering a _PPC change notification for one of them. Obviously, that global change affects all CPUs, not just the notified one, and it needs to be acted upon by cpufreq. The intel_pstate driver is able to detect such global changes of the settings, but it also needs to update policy limits for all CPUs if that happens, in particular if turbo frequencies are enabled globally - to allow them to be used. For this reason, introduce a new cpufreq driver callback to be invoked on _PPC notifications, if present, instead of simply calling cpufreq_update_policy() for the notified CPU and make intel_pstate use it to trigger policy updates for all CPUs in the system if global settings change. 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/acpi/processor_perflib.c2
-rw-r--r--drivers/cpufreq/cpufreq.c16
-rw-r--r--drivers/cpufreq/intel_pstate.c24
-rw-r--r--include/linux/cpufreq.h4
4 files changed, 45 insertions, 1 deletions
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index a303fd0e108c..c73d3a62799a 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -181,7 +181,7 @@ void acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
181 acpi_processor_ppc_ost(pr->handle, 0); 181 acpi_processor_ppc_ost(pr->handle, 0);
182 } 182 }
183 if (ret >= 0) 183 if (ret >= 0)
184 cpufreq_update_policy(pr->id); 184 cpufreq_update_limits(pr->id);
185} 185}
186 186
187int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) 187int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index e10922709d13..bb63347f6af1 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2370,6 +2370,22 @@ unlock:
2370} 2370}
2371EXPORT_SYMBOL(cpufreq_update_policy); 2371EXPORT_SYMBOL(cpufreq_update_policy);
2372 2372
2373/**
2374 * cpufreq_update_limits - Update policy limits for a given CPU.
2375 * @cpu: CPU to update the policy limits for.
2376 *
2377 * Invoke the driver's ->update_limits callback if present or call
2378 * cpufreq_update_policy() for @cpu.
2379 */
2380void cpufreq_update_limits(unsigned int cpu)
2381{
2382 if (cpufreq_driver->update_limits)
2383 cpufreq_driver->update_limits(cpu);
2384 else
2385 cpufreq_update_policy(cpu);
2386}
2387EXPORT_SYMBOL_GPL(cpufreq_update_limits);
2388
2373/********************************************************************* 2389/*********************************************************************
2374 * BOOST * 2390 * BOOST *
2375 *********************************************************************/ 2391 *********************************************************************/
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index b599c7318aab..e2191a570ade 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -179,6 +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 * @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
183 * P-state capacity. 184 * P-state capacity.
184 * @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
@@ -187,6 +188,7 @@ struct vid_data {
187struct global_params { 188struct global_params {
188 bool no_turbo; 189 bool no_turbo;
189 bool turbo_disabled; 190 bool turbo_disabled;
191 bool turbo_disabled_s;
190 int max_perf_pct; 192 int max_perf_pct;
191 int min_perf_pct; 193 int min_perf_pct;
192}; 194};
@@ -897,6 +899,25 @@ static void intel_pstate_update_policies(void)
897 cpufreq_update_policy(cpu); 899 cpufreq_update_policy(cpu);
898} 900}
899 901
902static void intel_pstate_update_limits(unsigned int cpu)
903{
904 mutex_lock(&intel_pstate_driver_lock);
905
906 update_turbo_state();
907 /*
908 * If turbo has been turned on or off globally, policy limits for
909 * all CPUs need to be updated to reflect that.
910 */
911 if (global.turbo_disabled_s != global.turbo_disabled) {
912 global.turbo_disabled_s = global.turbo_disabled;
913 intel_pstate_update_policies();
914 } else {
915 cpufreq_update_policy(cpu);
916 }
917
918 mutex_unlock(&intel_pstate_driver_lock);
919}
920
900/************************** sysfs begin ************************/ 921/************************** sysfs begin ************************/
901#define show_one(file_name, object) \ 922#define show_one(file_name, object) \
902 static ssize_t show_##file_name \ 923 static ssize_t show_##file_name \
@@ -2138,6 +2159,7 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
2138 /* cpuinfo and default policy values */ 2159 /* cpuinfo and default policy values */
2139 policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling; 2160 policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling;
2140 update_turbo_state(); 2161 update_turbo_state();
2162 global.turbo_disabled_s = global.turbo_disabled;
2141 policy->cpuinfo.max_freq = global.turbo_disabled ? 2163 policy->cpuinfo.max_freq = global.turbo_disabled ?
2142 cpu->pstate.max_pstate : cpu->pstate.turbo_pstate; 2164 cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
2143 policy->cpuinfo.max_freq *= cpu->pstate.scaling; 2165 policy->cpuinfo.max_freq *= cpu->pstate.scaling;
@@ -2182,6 +2204,7 @@ static struct cpufreq_driver intel_pstate = {
2182 .init = intel_pstate_cpu_init, 2204 .init = intel_pstate_cpu_init,
2183 .exit = intel_pstate_cpu_exit, 2205 .exit = intel_pstate_cpu_exit,
2184 .stop_cpu = intel_pstate_stop_cpu, 2206 .stop_cpu = intel_pstate_stop_cpu,
2207 .update_limits = intel_pstate_update_limits,
2185 .name = "intel_pstate", 2208 .name = "intel_pstate",
2186}; 2209};
2187 2210
@@ -2316,6 +2339,7 @@ static struct cpufreq_driver intel_cpufreq = {
2316 .init = intel_cpufreq_cpu_init, 2339 .init = intel_cpufreq_cpu_init,
2317 .exit = intel_pstate_cpu_exit, 2340 .exit = intel_pstate_cpu_exit,
2318 .stop_cpu = intel_cpufreq_stop_cpu, 2341 .stop_cpu = intel_cpufreq_stop_cpu,
2342 .update_limits = intel_pstate_update_limits,
2319 .name = "intel_cpufreq", 2343 .name = "intel_cpufreq",
2320}; 2344};
2321 2345
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index b160e98076e3..5005ea40364f 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -195,6 +195,7 @@ void disable_cpufreq(void);
195u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy); 195u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy);
196int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); 196int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
197void cpufreq_update_policy(unsigned int cpu); 197void cpufreq_update_policy(unsigned int cpu);
198void cpufreq_update_limits(unsigned int cpu);
198bool have_governor_per_policy(void); 199bool have_governor_per_policy(void);
199struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy); 200struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy);
200void cpufreq_enable_fast_switch(struct cpufreq_policy *policy); 201void cpufreq_enable_fast_switch(struct cpufreq_policy *policy);
@@ -322,6 +323,9 @@ struct cpufreq_driver {
322 /* should be defined, if possible */ 323 /* should be defined, if possible */
323 unsigned int (*get)(unsigned int cpu); 324 unsigned int (*get)(unsigned int cpu);
324 325
326 /* Called to update policy limits on firmware notifications. */
327 void (*update_limits)(unsigned int cpu);
328
325 /* optional */ 329 /* optional */
326 int (*bios_limit)(int cpu, unsigned int *limit); 330 int (*bios_limit)(int cpu, unsigned int *limit);
327 331