lpm_levels: Avoid race by preventing hotplug during lpm probe

When cluster enters a low power mode, the mode entered is stored
in last_level. During LPM driver probe last_level is initialized
to default level, if a core in that cluster is online.

If all the cores in the cluster are hotplugged after initializing
the last_level and before the per cluster data structures are
initialized, cluster enters low power mode but does not update
last_level as the data structures are not available. In this case
when a core in this cluster is coming online and last_level indicates
default level, assumes cluster did not enter any low power mode,
the update of flags to reflect the cores as active for this cluster
does not happen. This makes driver to select system level low power
mode as if this cluster is in low power mode eventhough it is out
of low power mode.

To avoid this race, prevent cores hotplug during lpm probe.

Change-Id: I1d0c51c52e54ab30239b2fca11040f134315fe61
Signed-off-by: Anil Kumar Mamidala <amami@codeaurora.org>
This commit is contained in:
Anil Kumar Mamidala 2016-04-19 13:16:38 +05:30 committed by Gerrit - the friendly Code Review server
parent c69a4a60de
commit bbb4e7c41e
1 changed files with 5 additions and 2 deletions

View File

@ -1121,10 +1121,12 @@ static int lpm_probe(struct platform_device *pdev)
int size;
struct kobject *module_kobj = NULL;
get_online_cpus();
lpm_root_node = lpm_of_parse_cluster(pdev);
if (IS_ERR_OR_NULL(lpm_root_node)) {
pr_err("%s(): Failed to probe low power modes\n", __func__);
put_online_cpus();
return PTR_ERR(lpm_root_node);
}
@ -1137,7 +1139,6 @@ static int lpm_probe(struct platform_device *pdev)
* core. BUG in existing code but no known issues possibly because of
* how late lpm_levels gets initialized.
*/
register_hotcpu_notifier(&lpm_cpu_nblk);
get_cpu();
on_each_cpu(setup_broadcast_timer, (void *)true, 1);
put_cpu();
@ -1148,6 +1149,7 @@ static int lpm_probe(struct platform_device *pdev)
if (ret) {
pr_err("%s: Failed initializing scm_handoff_lock (%d)\n",
__func__, ret);
put_online_cpus();
return ret;
}
@ -1157,12 +1159,13 @@ static int lpm_probe(struct platform_device *pdev)
register_cluster_lpm_stats(lpm_root_node, NULL);
ret = cluster_cpuidle_register(lpm_root_node);
put_online_cpus();
if (ret) {
pr_err("%s()Failed to register with cpuidle framework\n",
__func__);
goto failed;
}
register_hotcpu_notifier(&lpm_cpu_nblk);
module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
if (!module_kobj) {
pr_err("%s: cannot find kobject for module %s\n",