summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2013-03-27 15:58:57 (GMT)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-03-31 23:11:34 (GMT)
commit7bd353a995d9049262661d85811d6109140582a3 (patch)
tree65535a5142ec5063547bc5b77f8ff03e6979816b /drivers
parent0d1857a1b987ef874aeb4b99c9c385fa5645bf61 (diff)
downloadlinux-7bd353a995d9049262661d85811d6109140582a3.tar.xz
cpufreq: Add per policy governor-init/exit infrastructure
Currently, there can't be multiple instances of single governor_type. If we have a multi-package system, where we have multiple instances of struct policy (per package), we can't have multiple instances of same governor. i.e. We can't have multiple instances of ondemand governor for multiple packages. Governors directory in sysfs is created at /sys/devices/system/cpu/cpufreq/ governor-name/. Which again reflects that there can be only one instance of a governor_type in the system. This is a bottleneck for multicluster system, where we want different packages to use same governor type, but with different tunables. This patch is inclined towards providing this infrastructure. Because we are required to allocate governor's resources dynamically now, we must do it at policy creation and end. And so got CPUFREQ_GOV_POLICY_INIT/EXIT. 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.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index c5996fe..08df7a1 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1070,6 +1070,8 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
/* If cpu is last user of policy, free policy */
if (cpus == 1) {
+ __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
+
lock_policy_rwsem_read(cpu);
kobj = &data->kobj;
cmp = &data->kobj_unregister;
@@ -1651,7 +1653,7 @@ EXPORT_SYMBOL(cpufreq_get_policy);
static int __cpufreq_set_policy(struct cpufreq_policy *data,
struct cpufreq_policy *policy)
{
- int ret = 0;
+ int ret = 0, failed = 1;
pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
policy->min, policy->max);
@@ -1705,18 +1707,31 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
pr_debug("governor switch\n");
/* end old governor */
- if (data->governor)
+ if (data->governor) {
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
+ __cpufreq_governor(data,
+ CPUFREQ_GOV_POLICY_EXIT);
+ }
/* start new governor */
data->governor = policy->governor;
- if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
+ if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
+ if (!__cpufreq_governor(data, CPUFREQ_GOV_START))
+ failed = 0;
+ else
+ __cpufreq_governor(data,
+ CPUFREQ_GOV_POLICY_EXIT);
+ }
+
+ if (failed) {
/* new governor failed, so re-start old one */
pr_debug("starting governor %s failed\n",
data->governor->name);
if (old_gov) {
data->governor = old_gov;
__cpufreq_governor(data,
+ CPUFREQ_GOV_POLICY_INIT);
+ __cpufreq_governor(data,
CPUFREQ_GOV_START);
}
ret = -EINVAL;