Commit 4bc384ae authored by Viresh Kumar's avatar Viresh Kumar Committed by Rafael J. Wysocki

cpufreq: propagate errors returned from __cpufreq_governor()

Return codes aren't honored properly in cpufreq_set_policy(). This can
lead to two problems:
- wrong errors propagated to sysfs
- we try to do next state-change even if the previous one failed

cpufreq_governor_dbs() now returns proper errors on all invalid
state-transition requests and this code should honor that.
Reviewed-and-tested-by: default avatarPreeti U Murthy <preeti@linux.vnet.ibm.com>
Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 871ef3b5
...@@ -2295,16 +2295,31 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, ...@@ -2295,16 +2295,31 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
old_gov = policy->governor; old_gov = policy->governor;
/* end old governor */ /* end old governor */
if (old_gov) { if (old_gov) {
__cpufreq_governor(policy, CPUFREQ_GOV_STOP); ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
if (ret) {
/* This can happen due to race with other operations */
pr_debug("%s: Failed to Stop Governor: %s (%d)\n",
__func__, old_gov->name, ret);
return ret;
}
up_write(&policy->rwsem); up_write(&policy->rwsem);
__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
down_write(&policy->rwsem); down_write(&policy->rwsem);
if (ret) {
pr_err("%s: Failed to Exit Governor: %s (%d)\n",
__func__, old_gov->name, ret);
return ret;
}
} }
/* start new governor */ /* start new governor */
policy->governor = new_policy->governor; policy->governor = new_policy->governor;
if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) { ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) if (!ret) {
ret = __cpufreq_governor(policy, CPUFREQ_GOV_START);
if (!ret)
goto out; goto out;
up_write(&policy->rwsem); up_write(&policy->rwsem);
...@@ -2316,11 +2331,13 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, ...@@ -2316,11 +2331,13 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
pr_debug("starting governor %s failed\n", policy->governor->name); pr_debug("starting governor %s failed\n", policy->governor->name);
if (old_gov) { if (old_gov) {
policy->governor = old_gov; policy->governor = old_gov;
__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT); if (__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT))
policy->governor = NULL;
else
__cpufreq_governor(policy, CPUFREQ_GOV_START); __cpufreq_governor(policy, CPUFREQ_GOV_START);
} }
return -EINVAL; return ret;
out: out:
pr_debug("governor: change or update limits\n"); pr_debug("governor: change or update limits\n");
......
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