Commit ba44e51e authored by Viresh Kumar's avatar Viresh Kumar Committed by Greg Kroah-Hartman

cpufreq: Schedule work for the first-online CPU on resume

commit c75de0ac upstream.

All CPUs leaving the first-online CPU are hotplugged out on suspend and
and cpufreq core stops managing them.

On resume, we need to call cpufreq_update_policy() for this CPU's policy
to make sure its frequency is in sync with cpufreq's cached value, as it
might have got updated by hardware during suspend/resume.

The policies are always added to the top of the policy-list. So, in
normal circumstances, CPU 0's policy will be the last one in the list.
And so the code checks for the last policy.

But there are cases where it will fail. Consider quad-core system, with
policy-per core. If CPU0 is hotplugged out and added back again, the
last policy will be on CPU1 :(

To fix this in a proper way, always look for the policy of the first
online CPU. That way we will be sure that we are calling
cpufreq_update_policy() for the only CPU that wasn't hotplugged out.

Fixes: 2f0aea93 ("cpufreq: suspend governors on system suspend/hibernate")
Reported-by: default avatarSaravana Kannan <skannan@codeaurora.org>
Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Acked-by: default avatarSaravana Kannan <skannan@codeaurora.org>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 28d96fb0
...@@ -1724,15 +1724,18 @@ void cpufreq_resume(void) ...@@ -1724,15 +1724,18 @@ void cpufreq_resume(void)
|| __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS)) || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))
pr_err("%s: Failed to start governor for policy: %p\n", pr_err("%s: Failed to start governor for policy: %p\n",
__func__, policy); __func__, policy);
}
/* /*
* schedule call cpufreq_update_policy() for boot CPU, i.e. last * schedule call cpufreq_update_policy() for first-online CPU, as that
* policy in list. It will verify that the current freq is in * wouldn't be hotplugged-out on suspend. It will verify that the
* sync with what we believe it to be. * current freq is in sync with what we believe it to be.
*/ */
if (list_is_last(&policy->policy_list, &cpufreq_policy_list)) policy = cpufreq_cpu_get_raw(cpumask_first(cpu_online_mask));
if (WARN_ON(!policy))
return;
schedule_work(&policy->update); schedule_work(&policy->update);
}
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment