Giovanni Gherdovich 32f938
From: Stuart Hayes <stuart.w.hayes@gmail.com>
Giovanni Gherdovich 32f938
Date: Wed, 2 Nov 2022 14:59:57 -0500
Giovanni Gherdovich 32f938
Subject: cpufreq: ACPI: Defer setting boost MSRs
Giovanni Gherdovich 32f938
Patch-mainline: v6.2-rc1
Giovanni Gherdovich 32f938
Git-commit: 13fdbc8b8da6a2325cad3359c9a70504b0ff2f93
Giovanni Gherdovich 32f938
References: bsc#1205485
Giovanni Gherdovich 32f938
Giovanni Gherdovich 32f938
When acpi-cpufreq is loaded, boost is enabled on every CPU (by setting an
Giovanni Gherdovich 32f938
MSR) before the driver is registered with cpufreq.  This can be very time
Giovanni Gherdovich 32f938
consuming, because it is done with a CPU hotplug startup callback, and
Giovanni Gherdovich 32f938
cpuhp_setup_state() schedules the callback (cpufreq_boost_online()) to run
Giovanni Gherdovich 32f938
on each CPU one at a time, waiting for each to run before calling the next.
Giovanni Gherdovich 32f938
Giovanni Gherdovich 32f938
If cpufreq_register_driver() fails--if, for example, there are no ACPI
Giovanni Gherdovich 32f938
P-states present--this is wasted time.
Giovanni Gherdovich 32f938
Giovanni Gherdovich 32f938
Since cpufreq already sets up a CPU hotplug startup callback if and when
Giovanni Gherdovich 32f938
acpi-cpufreq is registered, set the boost MSRs in acpi_cpufreq_cpu_init(),
Giovanni Gherdovich 32f938
which is called by the cpufreq cpuhp callback.  This allows acpi-cpufreq to
Giovanni Gherdovich 32f938
exit quickly if it is loaded but not needed.
Giovanni Gherdovich 32f938
Giovanni Gherdovich 32f938
On one system with 192 CPUs, this patch speeds up boot by about 30 seconds.
Giovanni Gherdovich 32f938
Giovanni Gherdovich 32f938
Signed-off-by: Stuart Hayes <stuart.w.hayes@gmail.com>
Giovanni Gherdovich 32f938
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Giovanni Gherdovich 32f938
Acked-by: Giovanni Gherdovich <ggherdovich@suse.cz>
Giovanni Gherdovich 32f938
---
Giovanni Gherdovich 32f938
 drivers/cpufreq/acpi-cpufreq.c |   31 +++----------------------------
Giovanni Gherdovich 32f938
 1 file changed, 3 insertions(+), 28 deletions(-)
Giovanni Gherdovich 32f938
Giovanni Gherdovich 32f938
--- a/drivers/cpufreq/acpi-cpufreq.c
Giovanni Gherdovich 32f938
+++ b/drivers/cpufreq/acpi-cpufreq.c
Giovanni Gherdovich 32f938
@@ -530,15 +530,6 @@ static void free_acpi_perf_data(void)
Giovanni Gherdovich 32f938
 	free_percpu(acpi_perf_data);
Giovanni Gherdovich 32f938
 }
Giovanni Gherdovich 32f938
 
Giovanni Gherdovich 32f938
-static int cpufreq_boost_online(unsigned int cpu)
Giovanni Gherdovich 32f938
-{
Giovanni Gherdovich 32f938
-	/*
Giovanni Gherdovich 32f938
-	 * On the CPU_UP path we simply keep the boost-disable flag
Giovanni Gherdovich 32f938
-	 * in sync with the current global state.
Giovanni Gherdovich 32f938
-	 */
Giovanni Gherdovich 32f938
-	return boost_set_msr(acpi_cpufreq_driver.boost_enabled);
Giovanni Gherdovich 32f938
-}
Giovanni Gherdovich 32f938
-
Giovanni Gherdovich 32f938
 static int cpufreq_boost_down_prep(unsigned int cpu)
Giovanni Gherdovich 32f938
 {
Giovanni Gherdovich 32f938
 	/*
Giovanni Gherdovich 32f938
@@ -889,6 +880,8 @@ static int acpi_cpufreq_cpu_init(struct
Giovanni Gherdovich 32f938
 	policy->fast_switch_possible = !acpi_pstate_strict &&
Giovanni Gherdovich 32f938
 		!(policy_is_shared(policy) && policy->shared_type != CPUFREQ_SHARED_TYPE_ANY);
Giovanni Gherdovich 32f938
 
Giovanni Gherdovich 32f938
+	set_boost(policy, acpi_cpufreq_driver.boost_enabled);
Giovanni Gherdovich 32f938
+
Giovanni Gherdovich 32f938
 	return result;
Giovanni Gherdovich 32f938
 
Giovanni Gherdovich 32f938
 err_unreg:
Giovanni Gherdovich 32f938
@@ -908,6 +901,7 @@ static int acpi_cpufreq_cpu_exit(struct
Giovanni Gherdovich 32f938
 
Giovanni Gherdovich 32f938
 	pr_debug("%s\n", __func__);
Giovanni Gherdovich 32f938
 
Giovanni Gherdovich 32f938
+	cpufreq_boost_down_prep(policy->cpu);
Giovanni Gherdovich 32f938
 	policy->fast_switch_possible = false;
Giovanni Gherdovich 32f938
 	policy->driver_data = NULL;
Giovanni Gherdovich 32f938
 	acpi_processor_unregister_performance(data->acpi_perf_cpu);
Giovanni Gherdovich 32f938
@@ -975,25 +969,9 @@ static void __init acpi_cpufreq_boost_in
Giovanni Gherdovich 32f938
 	acpi_cpufreq_driver.set_boost = set_boost;
Giovanni Gherdovich 32f938
 	acpi_cpufreq_driver.boost_enabled = boost_state(0);
Giovanni Gherdovich 32f938
 
Giovanni Gherdovich 32f938
-	/*
Giovanni Gherdovich 32f938
-	 * This calls the online callback on all online cpu and forces all
Giovanni Gherdovich 32f938
-	 * MSRs to the same value.
Giovanni Gherdovich 32f938
-	 */
Giovanni Gherdovich 32f938
-	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "cpufreq/acpi:online",
Giovanni Gherdovich 32f938
-				cpufreq_boost_online, cpufreq_boost_down_prep);
Giovanni Gherdovich 32f938
-	if (ret < 0) {
Giovanni Gherdovich 32f938
-		pr_err("acpi_cpufreq: failed to register hotplug callbacks\n");
Giovanni Gherdovich 32f938
-		return;
Giovanni Gherdovich 32f938
-	}
Giovanni Gherdovich 32f938
 	acpi_cpufreq_online = ret;
Giovanni Gherdovich 32f938
 }
Giovanni Gherdovich 32f938
 
Giovanni Gherdovich 32f938
-static void acpi_cpufreq_boost_exit(void)
Giovanni Gherdovich 32f938
-{
Giovanni Gherdovich 32f938
-	if (acpi_cpufreq_online > 0)
Giovanni Gherdovich 32f938
-		cpuhp_remove_state_nocalls(acpi_cpufreq_online);
Giovanni Gherdovich 32f938
-}
Giovanni Gherdovich 32f938
-
Giovanni Gherdovich 32f938
 static int __init acpi_cpufreq_init(void)
Giovanni Gherdovich 32f938
 {
Giovanni Gherdovich 32f938
 	int ret;
Giovanni Gherdovich 32f938
@@ -1035,7 +1013,6 @@ static int __init acpi_cpufreq_init(void
Giovanni Gherdovich 32f938
 	ret = cpufreq_register_driver(&acpi_cpufreq_driver);
Giovanni Gherdovich 32f938
 	if (ret) {
Giovanni Gherdovich 32f938
 		free_acpi_perf_data();
Giovanni Gherdovich 32f938
-		acpi_cpufreq_boost_exit();
Giovanni Gherdovich 32f938
 	}
Giovanni Gherdovich 32f938
 	return ret;
Giovanni Gherdovich 32f938
 }
Giovanni Gherdovich 32f938
@@ -1044,8 +1021,6 @@ static void __exit acpi_cpufreq_exit(voi
Giovanni Gherdovich 32f938
 {
Giovanni Gherdovich 32f938
 	pr_debug("%s\n", __func__);
Giovanni Gherdovich 32f938
 
Giovanni Gherdovich 32f938
-	acpi_cpufreq_boost_exit();
Giovanni Gherdovich 32f938
-
Giovanni Gherdovich 32f938
 	cpufreq_unregister_driver(&acpi_cpufreq_driver);
Giovanni Gherdovich 32f938
 
Giovanni Gherdovich 32f938
 	free_acpi_perf_data();