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; \
}
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;
}
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);
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;
}
}
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)
{