]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/cpufreq/cpufreq.c
config: tegra3: enable /dev mount with ACL
[linux-2.6.git] / drivers / cpufreq / cpufreq.c
index 65fba49d3f070c1467ba82ac21ed3d90e9588bbb..02e8c9120d6b39407bb3a9886a4cb3e3ffec894c 100644 (file)
@@ -390,7 +390,7 @@ static ssize_t store_##file_name                                    \
                return -EINVAL;                                         \
                                                                        \
        ret = __cpufreq_set_policy(policy, &new_policy);                \
-       policy->user_policy.object = policy->object;                    \
+       policy->user_policy.object = new_policy.object;                 \
                                                                        \
        return ret ? ret : count;                                       \
 }
@@ -1449,8 +1449,10 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
 
        pr_debug("target for CPU %u: %u kHz, relation %u\n", policy->cpu,
                target_freq, relation);
+       trace_cpu_scale(policy->cpu, policy->cur, POWER_CPU_SCALE_START);
        if (cpu_online(policy->cpu) && cpufreq_driver->target)
                retval = cpufreq_driver->target(policy, target_freq, relation);
+       trace_cpu_scale(policy->cpu, target_freq, POWER_CPU_SCALE_DONE);
 
        return retval;
 }
@@ -1633,10 +1635,14 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
                                struct cpufreq_policy *policy)
 {
        int ret = 0;
+       unsigned int qmin, qmax;
        unsigned int pmin = policy->min;
        unsigned int pmax = policy->max;
-       unsigned int qmin = pm_qos_request(PM_QOS_CPU_FREQ_MIN);
-       unsigned int qmax = pm_qos_request(PM_QOS_CPU_FREQ_MAX);
+
+       qmin = min((unsigned int)pm_qos_request(PM_QOS_CPU_FREQ_MIN),
+                  data->user_policy.max);
+       qmax = max((unsigned int)pm_qos_request(PM_QOS_CPU_FREQ_MAX),
+                  data->user_policy.min);
 
        pr_debug("setting new policy for CPU %u: %u - %u (%u - %u) kHz\n",
                policy->cpu, pmin, pmax, qmin, qmax);
@@ -1648,7 +1654,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
        memcpy(&policy->cpuinfo, &data->cpuinfo,
                                sizeof(struct cpufreq_cpuinfo));
 
-       if (policy->min > data->max || policy->max < data->min) {
+       if (policy->min > data->user_policy.max ||
+           policy->max < data->user_policy.min) {
                ret = -EINVAL;
                goto error_out;
        }
@@ -1779,6 +1786,70 @@ no_policy:
 }
 EXPORT_SYMBOL(cpufreq_update_policy);
 
+/*
+ *     cpufreq_set_gov - set governor for a cpu
+ *     @cpu: CPU whose governor needs to be changed
+ *     @target_gov: new governor to be set
+ */
+int cpufreq_set_gov(char *target_gov, unsigned int cpu)
+{
+       int ret = 0;
+       struct cpufreq_policy new_policy;
+       struct cpufreq_policy *cur_policy;
+
+       if (target_gov == NULL)
+               return -EINVAL;
+
+       /* Get current governer */
+       cur_policy = cpufreq_cpu_get(cpu);
+       if (!cur_policy)
+               return -EINVAL;
+
+       if (lock_policy_rwsem_read(cur_policy->cpu) < 0) {
+               ret = -EINVAL;
+               goto err_out;
+       }
+
+       if (cur_policy->governor)
+               ret = strncmp(cur_policy->governor->name, target_gov,
+                                       strlen(target_gov));
+       else {
+               unlock_policy_rwsem_read(cur_policy->cpu);
+               ret = -EINVAL;
+               goto err_out;
+       }
+       unlock_policy_rwsem_read(cur_policy->cpu);
+
+       if (!ret) {
+               pr_debug(" Target governer & current governer is same\n");
+               ret = -EINVAL;
+               goto err_out;
+       } else {
+               new_policy = *cur_policy;
+               if (cpufreq_parse_governor(target_gov, &new_policy.policy,
+                               &new_policy.governor)) {
+                       ret = -EINVAL;
+                       goto err_out;
+               }
+
+               if (lock_policy_rwsem_write(cur_policy->cpu) < 0) {
+                       ret = -EINVAL;
+                       goto err_out;
+               }
+
+               ret = __cpufreq_set_policy(cur_policy, &new_policy);
+
+               cur_policy->user_policy.policy = cur_policy->policy;
+               cur_policy->user_policy.governor = cur_policy->governor;
+
+               unlock_policy_rwsem_write(cur_policy->cpu);
+       }
+err_out:
+       cpufreq_cpu_put(cur_policy);
+       return ret;
+}
+EXPORT_SYMBOL(cpufreq_set_gov);
+
 static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb,
                                        unsigned long action, void *hcpu)
 {