cpufreq: propagate errors returned from __cpufreq_governor()
authorViresh Kumar <viresh.kumar@linaro.org>
Sat, 18 Jul 2015 06:01:03 +0000 (11:31 +0530)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 20 Jul 2015 23:12:02 +0000 (01:12 +0200)
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>
drivers/cpufreq/cpufreq.c

index a7b6ac6e048e9b3a52f684dc1ee086f4cd1c8300..a3e8fb61cbcccf01429ead6e4096c5b89d95aabe 100644 (file)
@@ -2295,16 +2295,31 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
        old_gov = policy->governor;
        /* end old governor */
        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);
-               __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
+               ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
                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 */
        policy->governor = new_policy->governor;
-       if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) {
-               if (!__cpufreq_governor(policy, CPUFREQ_GOV_START))
+       ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
+       if (!ret) {
+               ret = __cpufreq_governor(policy, CPUFREQ_GOV_START);
+               if (!ret)
                        goto out;
 
                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);
        if (old_gov) {
                policy->governor = old_gov;
-               __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
-               __cpufreq_governor(policy, CPUFREQ_GOV_START);
+               if (__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT))
+                       policy->governor = NULL;
+               else
+                       __cpufreq_governor(policy, CPUFREQ_GOV_START);
        }
 
-       return -EINVAL;
+       return ret;
 
  out:
        pr_debug("governor: change or update limits\n");