| From 96c150ab868a54ea2d20cc718f68de53dadfb3a8 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 22 Jun 2021 21:11:39 +0200 |
| Subject: cpufreq: Make cpufreq_online() call driver->offline() on errors |
| |
| From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| |
| [ Upstream commit 3b7180573c250eb6e2a7eec54ae91f27472332ea ] |
| |
| In the CPU removal path the ->offline() callback provided by the |
| driver is always invoked before ->exit(), but in the cpufreq_online() |
| error path it is not, so ->exit() is expected to somehow know the |
| context in which it has been called and act accordingly. |
| |
| That is less than straightforward, so make cpufreq_online() invoke |
| the driver's ->offline() callback, if present, on errors before |
| ->exit() too. |
| |
| This only potentially affects intel_pstate. |
| |
| Fixes: 91a12e91dc39 ("cpufreq: Allow light-weight tear down and bring up of CPUs") |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Acked-by: Viresh Kumar <viresh.kumar@linaro.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/cpufreq/cpufreq.c | 11 ++++++++++- |
| 1 file changed, 10 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c |
| index 1e7e3f2ff09f..ebee0ad559fa 100644 |
| --- a/drivers/cpufreq/cpufreq.c |
| +++ b/drivers/cpufreq/cpufreq.c |
| @@ -1368,9 +1368,14 @@ static int cpufreq_online(unsigned int cpu) |
| goto out_free_policy; |
| } |
| |
| + /* |
| + * The initialization has succeeded and the policy is online. |
| + * If there is a problem with its frequency table, take it |
| + * offline and drop it. |
| + */ |
| ret = cpufreq_table_validate_and_sort(policy); |
| if (ret) |
| - goto out_exit_policy; |
| + goto out_offline_policy; |
| |
| /* related_cpus should at least include policy->cpus. */ |
| cpumask_copy(policy->related_cpus, policy->cpus); |
| @@ -1513,6 +1518,10 @@ out_destroy_policy: |
| |
| up_write(&policy->rwsem); |
| |
| +out_offline_policy: |
| + if (cpufreq_driver->offline) |
| + cpufreq_driver->offline(policy); |
| + |
| out_exit_policy: |
| if (cpufreq_driver->exit) |
| cpufreq_driver->exit(policy); |
| -- |
| 2.30.2 |
| |