Commit e804252b authored by Dave Jones's avatar Dave Jones

[CPUFREQ] Completely separate governors from policies.

Governors are for CPUfreq drivers which have a ->target callback,
Policies are for CPUfreq drivers which have a ->setpolicy callback.
Also, the "hardwired" governors "powersave" and "performance" are removed.
parent adff42b1
......@@ -109,13 +109,18 @@ static void cpufreq_cpu_put(struct cpufreq_policy *data)
int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
struct cpufreq_governor **governor)
{
if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_PERFORMANCE;
return 0;
} else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_POWERSAVE;
return 0;
} else {
if (!cpufreq_driver)
return -EINVAL;
if (cpufreq_driver->setpolicy) {
if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_PERFORMANCE;
return 0;
} else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_POWERSAVE;
return 0;
}
return -EINVAL;
} else {
struct cpufreq_governor *t;
down(&cpufreq_governor_sem);
if (!cpufreq_driver || !cpufreq_driver->target)
......@@ -123,7 +128,6 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
*governor = t;
*policy = CPUFREQ_POLICY_GOVERNOR;
up(&cpufreq_governor_sem);
return 0;
}
......@@ -190,16 +194,13 @@ store_one(scaling_max_freq,max);
*/
static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf)
{
switch (policy->policy) {
case CPUFREQ_POLICY_POWERSAVE:
if(policy->policy == CPUFREQ_POLICY_POWERSAVE)
return sprintf(buf, "powersave\n");
case CPUFREQ_POLICY_PERFORMANCE:
else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
return sprintf(buf, "performance\n");
case CPUFREQ_POLICY_GOVERNOR:
else if (policy->governor)
return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name);
default:
return -EINVAL;
}
return -EINVAL;
}
......@@ -246,15 +247,15 @@ static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy,
ssize_t i = 0;
struct cpufreq_governor *t;
i += sprintf(buf, "performance powersave");
if (!cpufreq_driver->target)
if (!cpufreq_driver->target) {
i += sprintf(buf, "performance powersave");
goto out;
}
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2)))
goto out;
i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name);
i += snprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name);
}
out:
i += sprintf(&buf[i], "\n");
......@@ -396,10 +397,12 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
spin_lock_irqsave(&cpufreq_driver_lock, flags);
cpufreq_cpu_data[cpu] = policy;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
policy->governor = NULL; /* to assure that the starting sequence is
* run in cpufreq_set_policy */
up(&policy->lock);
/* set default policy */
ret = cpufreq_set_policy(&new_policy);
if (ret)
goto err_out_unregister;
......@@ -622,33 +625,18 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_target);
static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
{
int ret = 0;
int ret = -EINVAL;
switch (policy->policy) {
case CPUFREQ_POLICY_POWERSAVE:
if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
}
break;
case CPUFREQ_POLICY_PERFORMANCE:
if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
}
break;
case CPUFREQ_POLICY_GOVERNOR:
ret = -EINVAL;
if (!try_module_get(policy->governor->owner))
break;
ret = policy->governor->governor(policy, event);
/* 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)
module_put(policy->governor->owner);
break;
default:
ret = -EINVAL;
}
if (!try_module_get(policy->governor->owner))
return -EINVAL;
ret = policy->governor->governor(policy, event);
/* 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)
module_put(policy->governor->owner);
return ret;
}
......@@ -680,11 +668,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
if (!governor)
return -EINVAL;
if (!strnicmp(governor->name,"powersave",CPUFREQ_NAME_LEN))
return -EBUSY;
if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN))
return -EBUSY;
down(&cpufreq_governor_sem);
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
......@@ -808,23 +791,24 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
data->policy = policy->policy;
ret = cpufreq_driver->setpolicy(policy);
} else {
if ((policy->policy != data->policy) ||
((policy->policy == CPUFREQ_POLICY_GOVERNOR) && (policy->governor != data->governor))) {
if (policy->governor != data->governor) {
/* save old, working values */
unsigned int old_pol = data->policy;
struct cpufreq_governor *old_gov = data->governor;
/* end old governor */
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
if (data->governor)
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
/* start new governor */
data->policy = policy->policy;
data->governor = policy->governor;
if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
/* new governor failed, so re-start old one */
data->policy = old_pol;
data->governor = old_gov;
__cpufreq_governor(data, CPUFREQ_GOV_START);
if (old_gov) {
data->governor = old_gov;
__cpufreq_governor(data, CPUFREQ_GOV_START);
}
ret = -EINVAL;
goto error_out;
}
/* might be a policy change, too, so fall through */
}
......
......@@ -126,20 +126,20 @@ static int cpufreq_proc_read (
p += sprintf(p, "CPU%3d %9d kHz (%3d %%) - %9d kHz (%3d %%) - ",
i , policy.min, min_pctg, policy.max, max_pctg);
switch (policy.policy) {
case CPUFREQ_POLICY_POWERSAVE:
p += sprintf(p, "powersave\n");
break;
case CPUFREQ_POLICY_PERFORMANCE:
p += sprintf(p, "performance\n");
break;
case CPUFREQ_POLICY_GOVERNOR:
if (policy.policy) {
switch (policy.policy) {
case CPUFREQ_POLICY_POWERSAVE:
p += sprintf(p, "powersave\n");
break;
case CPUFREQ_POLICY_PERFORMANCE:
p += sprintf(p, "performance\n");
break;
default:
p += sprintf(p, "INVALID\n");
break;
}
} else
p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name);
break;
default:
p += sprintf(p, "INVALID\n");
break;
}
}
end:
len = (p - page);
......
......@@ -36,11 +36,13 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list);
#define CPUFREQ_POLICY_NOTIFIER (1)
/********************** cpufreq policy notifiers *********************/
/* if (cpufreq_driver->target) exists, the ->governor decides what frequency
* within the limits is used. If (cpufreq_driver->setpolicy> exists, these
* two generic policies are available:
*/
#define CPUFREQ_POLICY_POWERSAVE (1)
#define CPUFREQ_POLICY_PERFORMANCE (2)
#define CPUFREQ_POLICY_GOVERNOR (3)
/* Frequency values here are CPU kHz so that hardware which doesn't run
* with some frequencies can complain without having to guess what per
......@@ -151,6 +153,7 @@ int cpufreq_governor(unsigned int cpu, unsigned int event);
int cpufreq_register_governor(struct cpufreq_governor *governor);
void cpufreq_unregister_governor(struct cpufreq_governor *governor);
/*********************************************************************
* CPUFREQ DRIVER INTERFACE *
*********************************************************************/
......@@ -221,7 +224,6 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpu
/*********************************************************************
* CPUFREQ USERSPACE GOVERNOR *
*********************************************************************/
extern struct cpufreq_governor cpufreq_gov_userspace;
int cpufreq_gov_userspace_init(void);
int cpufreq_setmax(unsigned int cpu);
......@@ -279,6 +281,19 @@ enum {
#endif /* CONFIG_CPU_FREQ_GOV_USERSPACE */
/*********************************************************************
* CPUFREQ DEFAULT GOVERNOR *
*********************************************************************/
#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE
extern struct cpufreq_governor cpufreq_gov_performance;
#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_performance
#elif CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
extern struct cpufreq_governor cpufreq_gov_userspace;
#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_userspace
#endif
/*********************************************************************
* FREQUENCY TABLE HELPERS *
*********************************************************************/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment