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: Preeti U Murthy <preeti@linux.vnet.ibm.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
871ef3b53a
commit
4bc384ae62
@ -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,
|
|||||||
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))
|
||||||
__cpufreq_governor(policy, CPUFREQ_GOV_START);
|
policy->governor = NULL;
|
||||||
|
else
|
||||||
|
__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");
|
||||||
|
Loading…
Reference in New Issue
Block a user