summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2013-08-06 17:23:10 (GMT)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-08-10 01:24:47 (GMT)
commitfe492f3f0332e23cc6ca4913e5a2ed78e1888902 (patch)
tree0e87539040aabaf02babc0edc49fbb27610b0e3b /drivers
parenteb608521f1e25a8c14295b6d9a3853c3cd8c6cf8 (diff)
downloadlinux-fe492f3f0332e23cc6ca4913e5a2ed78e1888902.tar.xz
cpufreq: Fix broken usage of governor->owner's refcount
The cpufreq governor owner refcount usage is broken. We should only increment that refcount when a CPUFREQ_GOV_POLICY_INIT event has come and it should only be decremented if CPUFREQ_GOV_POLICY_EXIT has come. Currently, there can be situations where the governor is in use, but we have allowed it to be unloaded which may result in undefined behavior. Let's fix it. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/cpufreq/cpufreq.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 37af929..f149e14 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1709,8 +1709,9 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
}
}
- if (!try_module_get(policy->governor->owner))
- return -EINVAL;
+ if (event == CPUFREQ_GOV_POLICY_INIT)
+ if (!try_module_get(policy->governor->owner))
+ return -EINVAL;
pr_debug("__cpufreq_governor for CPU %u, event %u\n",
policy->cpu, event);
@@ -1719,6 +1720,8 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
if ((!policy->governor_enabled && (event == CPUFREQ_GOV_STOP)) ||
(policy->governor_enabled && (event == CPUFREQ_GOV_START))) {
mutex_unlock(&cpufreq_governor_lock);
+ if (event == CPUFREQ_GOV_POLICY_INIT)
+ module_put(policy->governor->owner);
return -EBUSY;
}
@@ -1746,11 +1749,8 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
mutex_unlock(&cpufreq_governor_lock);
}
- /* we keep one module reference alive for
- each CPU governed by this CPU */
- if ((event != CPUFREQ_GOV_START) || ret)
- module_put(policy->governor->owner);
- if ((event == CPUFREQ_GOV_STOP) && !ret)
+ if (((event == CPUFREQ_GOV_POLICY_INIT) && ret) ||
+ ((event == CPUFREQ_GOV_POLICY_EXIT) && !ret))
module_put(policy->governor->owner);
return ret;