|
@@ -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");
|