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) ...@@ -109,13 +109,18 @@ static void cpufreq_cpu_put(struct cpufreq_policy *data)
int cpufreq_parse_governor (char *str_governor, unsigned int *policy, int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
struct cpufreq_governor **governor) struct cpufreq_governor **governor)
{ {
if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { if (!cpufreq_driver)
*policy = CPUFREQ_POLICY_PERFORMANCE; return -EINVAL;
return 0; if (cpufreq_driver->setpolicy) {
} else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_POWERSAVE; *policy = CPUFREQ_POLICY_PERFORMANCE;
return 0; return 0;
} else { } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_POWERSAVE;
return 0;
}
return -EINVAL;
} else {
struct cpufreq_governor *t; struct cpufreq_governor *t;
down(&cpufreq_governor_sem); down(&cpufreq_governor_sem);
if (!cpufreq_driver || !cpufreq_driver->target) if (!cpufreq_driver || !cpufreq_driver->target)
...@@ -123,7 +128,6 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy, ...@@ -123,7 +128,6 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
list_for_each_entry(t, &cpufreq_governor_list, governor_list) { list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
*governor = t; *governor = t;
*policy = CPUFREQ_POLICY_GOVERNOR;
up(&cpufreq_governor_sem); up(&cpufreq_governor_sem);
return 0; return 0;
} }
...@@ -190,16 +194,13 @@ store_one(scaling_max_freq,max); ...@@ -190,16 +194,13 @@ store_one(scaling_max_freq,max);
*/ */
static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf) static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf)
{ {
switch (policy->policy) { if(policy->policy == CPUFREQ_POLICY_POWERSAVE)
case CPUFREQ_POLICY_POWERSAVE:
return sprintf(buf, "powersave\n"); return sprintf(buf, "powersave\n");
case CPUFREQ_POLICY_PERFORMANCE: else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
return sprintf(buf, "performance\n"); return sprintf(buf, "performance\n");
case CPUFREQ_POLICY_GOVERNOR: else if (policy->governor)
return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name); 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, ...@@ -246,15 +247,15 @@ static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy,
ssize_t i = 0; ssize_t i = 0;
struct cpufreq_governor *t; struct cpufreq_governor *t;
i += sprintf(buf, "performance powersave"); if (!cpufreq_driver->target) {
i += sprintf(buf, "performance powersave");
if (!cpufreq_driver->target)
goto out; goto out;
}
list_for_each_entry(t, &cpufreq_governor_list, governor_list) { list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2))) if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2)))
goto out; goto out;
i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name); i += snprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name);
} }
out: out:
i += sprintf(&buf[i], "\n"); i += sprintf(&buf[i], "\n");
...@@ -396,10 +397,12 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) ...@@ -396,10 +397,12 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
spin_lock_irqsave(&cpufreq_driver_lock, flags); spin_lock_irqsave(&cpufreq_driver_lock, flags);
cpufreq_cpu_data[cpu] = policy; cpufreq_cpu_data[cpu] = policy;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 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); up(&policy->lock);
/* set default policy */ /* set default policy */
ret = cpufreq_set_policy(&new_policy); ret = cpufreq_set_policy(&new_policy);
if (ret) if (ret)
goto err_out_unregister; goto err_out_unregister;
...@@ -622,33 +625,18 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_target); ...@@ -622,33 +625,18 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_target);
static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
{ {
int ret = 0; int ret = -EINVAL;
switch (policy->policy) { if (!try_module_get(policy->governor->owner))
case CPUFREQ_POLICY_POWERSAVE: return -EINVAL;
if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); ret = policy->governor->governor(policy, event);
}
break; /* we keep one module reference alive for each CPU governed by this CPU */
case CPUFREQ_POLICY_PERFORMANCE: if ((event != CPUFREQ_GOV_START) || ret)
if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) { module_put(policy->governor->owner);
ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); if ((event == CPUFREQ_GOV_STOP) && !ret)
} module_put(policy->governor->owner);
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;
}
return ret; return ret;
} }
...@@ -680,11 +668,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) ...@@ -680,11 +668,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
if (!governor) if (!governor)
return -EINVAL; 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); down(&cpufreq_governor_sem);
list_for_each_entry(t, &cpufreq_governor_list, governor_list) { list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
...@@ -808,23 +791,24 @@ int cpufreq_set_policy(struct cpufreq_policy *policy) ...@@ -808,23 +791,24 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
data->policy = policy->policy; data->policy = policy->policy;
ret = cpufreq_driver->setpolicy(policy); ret = cpufreq_driver->setpolicy(policy);
} else { } else {
if ((policy->policy != data->policy) || if (policy->governor != data->governor) {
((policy->policy == CPUFREQ_POLICY_GOVERNOR) && (policy->governor != data->governor))) {
/* save old, working values */ /* save old, working values */
unsigned int old_pol = data->policy;
struct cpufreq_governor *old_gov = data->governor; struct cpufreq_governor *old_gov = data->governor;
/* end old governor */ /* end old governor */
__cpufreq_governor(data, CPUFREQ_GOV_STOP); if (data->governor)
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
/* start new governor */ /* start new governor */
data->policy = policy->policy;
data->governor = policy->governor; data->governor = policy->governor;
if (__cpufreq_governor(data, CPUFREQ_GOV_START)) { if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
/* new governor failed, so re-start old one */ /* new governor failed, so re-start old one */
data->policy = old_pol; if (old_gov) {
data->governor = old_gov; data->governor = old_gov;
__cpufreq_governor(data, CPUFREQ_GOV_START); __cpufreq_governor(data, CPUFREQ_GOV_START);
}
ret = -EINVAL;
goto error_out;
} }
/* might be a policy change, too, so fall through */ /* might be a policy change, too, so fall through */
} }
......
...@@ -126,20 +126,20 @@ static int cpufreq_proc_read ( ...@@ -126,20 +126,20 @@ static int cpufreq_proc_read (
p += sprintf(p, "CPU%3d %9d kHz (%3d %%) - %9d kHz (%3d %%) - ", p += sprintf(p, "CPU%3d %9d kHz (%3d %%) - %9d kHz (%3d %%) - ",
i , policy.min, min_pctg, policy.max, max_pctg); i , policy.min, min_pctg, policy.max, max_pctg);
switch (policy.policy) { if (policy.policy) {
case CPUFREQ_POLICY_POWERSAVE: switch (policy.policy) {
p += sprintf(p, "powersave\n"); case CPUFREQ_POLICY_POWERSAVE:
break; p += sprintf(p, "powersave\n");
case CPUFREQ_POLICY_PERFORMANCE: break;
p += sprintf(p, "performance\n"); case CPUFREQ_POLICY_PERFORMANCE:
break; p += sprintf(p, "performance\n");
case CPUFREQ_POLICY_GOVERNOR: break;
default:
p += sprintf(p, "INVALID\n");
break;
}
} else
p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name); p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name);
break;
default:
p += sprintf(p, "INVALID\n");
break;
}
} }
end: end:
len = (p - page); len = (p - page);
......
...@@ -36,11 +36,13 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list); ...@@ -36,11 +36,13 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list);
#define CPUFREQ_POLICY_NOTIFIER (1) #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_POWERSAVE (1)
#define CPUFREQ_POLICY_PERFORMANCE (2) #define CPUFREQ_POLICY_PERFORMANCE (2)
#define CPUFREQ_POLICY_GOVERNOR (3)
/* Frequency values here are CPU kHz so that hardware which doesn't run /* Frequency values here are CPU kHz so that hardware which doesn't run
* with some frequencies can complain without having to guess what per * with some frequencies can complain without having to guess what per
...@@ -151,6 +153,7 @@ int cpufreq_governor(unsigned int cpu, unsigned int event); ...@@ -151,6 +153,7 @@ int cpufreq_governor(unsigned int cpu, unsigned int event);
int cpufreq_register_governor(struct cpufreq_governor *governor); int cpufreq_register_governor(struct cpufreq_governor *governor);
void cpufreq_unregister_governor(struct cpufreq_governor *governor); void cpufreq_unregister_governor(struct cpufreq_governor *governor);
/********************************************************************* /*********************************************************************
* CPUFREQ DRIVER INTERFACE * * CPUFREQ DRIVER INTERFACE *
*********************************************************************/ *********************************************************************/
...@@ -221,7 +224,6 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpu ...@@ -221,7 +224,6 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpu
/********************************************************************* /*********************************************************************
* CPUFREQ USERSPACE GOVERNOR * * CPUFREQ USERSPACE GOVERNOR *
*********************************************************************/ *********************************************************************/
extern struct cpufreq_governor cpufreq_gov_userspace;
int cpufreq_gov_userspace_init(void); int cpufreq_gov_userspace_init(void);
int cpufreq_setmax(unsigned int cpu); int cpufreq_setmax(unsigned int cpu);
...@@ -279,6 +281,19 @@ enum { ...@@ -279,6 +281,19 @@ enum {
#endif /* CONFIG_CPU_FREQ_GOV_USERSPACE */ #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 * * 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