diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-12-10 13:27:14 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-12-10 13:27:14 +0000 |
commit | 630b6713472007f100b40bf100246ca169b23a14 (patch) | |
tree | 70af1436ba366fc704e0b770fb11ae70c91145a7 /xen/drivers/cpufreq | |
parent | ac677794d61dc7a6f92b16946863043da890c828 (diff) | |
download | xen-630b6713472007f100b40bf100246ca169b23a14.tar.gz xen-630b6713472007f100b40bf100246ca169b23a14.tar.bz2 xen-630b6713472007f100b40bf100246ca169b23a14.zip |
Add cpufreq governors: performance, powersave, userspace
This patch add 3 more governors beside original running ondemand
cpufreq governor.
performance governor is with best performance, keeping cpu always
running at highest freq;
powersave governor is with best power save effect, keeping cpu always
running at lowest freq;
userspace governor provide user setting freq ability;
Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
Diffstat (limited to 'xen/drivers/cpufreq')
-rw-r--r-- | xen/drivers/cpufreq/Makefile | 1 | ||||
-rw-r--r-- | xen/drivers/cpufreq/cpufreq.c | 48 | ||||
-rw-r--r-- | xen/drivers/cpufreq/cpufreq_misc_governors.c | 158 | ||||
-rw-r--r-- | xen/drivers/cpufreq/cpufreq_ondemand.c | 12 |
4 files changed, 219 insertions, 0 deletions
diff --git a/xen/drivers/cpufreq/Makefile b/xen/drivers/cpufreq/Makefile index c91c25b715..b87d12777f 100644 --- a/xen/drivers/cpufreq/Makefile +++ b/xen/drivers/cpufreq/Makefile @@ -1,3 +1,4 @@ obj-y += cpufreq.o obj-y += cpufreq_ondemand.o +obj-y += cpufreq_misc_governors.o obj-y += utility.o diff --git a/xen/drivers/cpufreq/cpufreq.c b/xen/drivers/cpufreq/cpufreq.c index 8777a8a822..185b0343d7 100644 --- a/xen/drivers/cpufreq/cpufreq.c +++ b/xen/drivers/cpufreq/cpufreq.c @@ -33,6 +33,7 @@ #include <xen/cpumask.h> #include <xen/list.h> #include <xen/sched.h> +#include <xen/string.h> #include <xen/timer.h> #include <xen/xmalloc.h> #include <xen/guest_access.h> @@ -52,6 +53,53 @@ struct cpufreq_dom { }; static LIST_HEAD(cpufreq_dom_list_head); +static LIST_HEAD(cpufreq_governor_list); + +static struct cpufreq_governor *__find_governor(const char *governor) +{ + struct cpufreq_governor *t; + + if (!governor) + return NULL; + + list_for_each_entry(t, &cpufreq_governor_list, governor_list) + if (!strnicmp(governor, t->name, CPUFREQ_NAME_LEN)) + return t; + + return NULL; +} + +int cpufreq_register_governor(struct cpufreq_governor *governor) +{ + if (!governor) + return -EINVAL; + + if (__find_governor(governor->name) != NULL) + return -EEXIST; + + list_add(&governor->governor_list, &cpufreq_governor_list); + return 0; +} + +int cpufreq_unregister_governor(struct cpufreq_governor *governor) +{ + int cpu = smp_processor_id(); + struct cpufreq_policy *policy = cpufreq_cpu_policy[cpu]; + + if (!governor || !policy) + return -EINVAL; + + /* error if unregister current cpufreq governor */ + if (governor == policy->governor) + return -EBUSY; + + if (__find_governor(governor->name) == NULL) + return -ENOENT; + + list_del(&governor->governor_list); + return 0; +} + int cpufreq_limit_change(unsigned int cpu) { struct processor_performance *perf = &processor_pminfo[cpu]->perf; diff --git a/xen/drivers/cpufreq/cpufreq_misc_governors.c b/xen/drivers/cpufreq/cpufreq_misc_governors.c new file mode 100644 index 0000000000..8b391d39f8 --- /dev/null +++ b/xen/drivers/cpufreq/cpufreq_misc_governors.c @@ -0,0 +1,158 @@ +/* + * xen/drivers/cpufreq/cpufreq_misc_gov.c + * + * Copyright (C) 2001 Russell King + * (C) 2002 - 2004 Dominik Brodowski <linux@brodo.de> + * + * Nov 2008 Liu Jinsong <jinsong.liu@intel.com> + * Porting cpufreq_userspace.c, cpufreq_performance.c, and + * cpufreq_powersave.c from Liunx 2.6.23 to Xen hypervisor + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <xen/init.h> +#include <xen/sched.h> +#include <acpi/cpufreq/cpufreq.h> + + +/* + * cpufreq userspace governor + */ +static int cpufreq_governor_userspace(struct cpufreq_policy *policy, + unsigned int event) +{ + int ret = 0; + + if (!policy) + return -EINVAL; + + switch (event) { + case CPUFREQ_GOV_START: + case CPUFREQ_GOV_STOP: + break; + case CPUFREQ_GOV_LIMITS: + if (policy->max < policy->cur) + ret = __cpufreq_driver_target(policy, policy->max, + CPUFREQ_RELATION_H); + else if (policy->min > policy->cur) + ret = __cpufreq_driver_target(policy, policy->min, + CPUFREQ_RELATION_L); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +struct cpufreq_governor cpufreq_gov_userspace = { + .name = "userspace", + .governor = cpufreq_governor_userspace, +}; + +static int __init cpufreq_gov_userspace_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_userspace); +} +__initcall(cpufreq_gov_userspace_init); + +static void cpufreq_gov_userspace_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_userspace); +} +__exitcall(cpufreq_gov_userspace_exit); + + +/* + * cpufreq performance governor + */ +static int cpufreq_governor_performance(struct cpufreq_policy *policy, + unsigned int event) +{ + int ret = 0; + + if (!policy) + return -EINVAL; + + switch (event) { + case CPUFREQ_GOV_START: + case CPUFREQ_GOV_STOP: + break; + case CPUFREQ_GOV_LIMITS: + ret = __cpufreq_driver_target(policy, policy->max, + CPUFREQ_RELATION_H); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +struct cpufreq_governor cpufreq_gov_performance = { + .name = "performance", + .governor = cpufreq_governor_performance, +}; + +static int __init cpufreq_gov_performance_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_performance); +} +__initcall(cpufreq_gov_performance_init); + +static void cpufreq_gov_performance_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_performance); +} +__exitcall(cpufreq_gov_performance_exit); + + +/* + * cpufreq powersave governor + */ +static int cpufreq_governor_powersave(struct cpufreq_policy *policy, + unsigned int event) +{ + int ret = 0; + + if (!policy) + return -EINVAL; + + switch (event) { + case CPUFREQ_GOV_START: + case CPUFREQ_GOV_STOP: + break; + case CPUFREQ_GOV_LIMITS: + ret = __cpufreq_driver_target(policy, policy->min, + CPUFREQ_RELATION_L); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +struct cpufreq_governor cpufreq_gov_powersave = { + .name = "powersave", + .governor = cpufreq_governor_powersave, +}; + +static int __init cpufreq_gov_powersave_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_powersave); +} +__initcall(cpufreq_gov_powersave_init); + +static void cpufreq_gov_powersave_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_powersave); +} +__exitcall(cpufreq_gov_powersave_exit); diff --git a/xen/drivers/cpufreq/cpufreq_ondemand.c b/xen/drivers/cpufreq/cpufreq_ondemand.c index d860407fca..655edc79e9 100644 --- a/xen/drivers/cpufreq/cpufreq_ondemand.c +++ b/xen/drivers/cpufreq/cpufreq_ondemand.c @@ -263,6 +263,18 @@ struct cpufreq_governor cpufreq_gov_dbs = { .governor = cpufreq_governor_dbs, }; +static int __init cpufreq_gov_dbs_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_dbs); +} +__initcall(cpufreq_gov_dbs_init); + +static void cpufreq_gov_dbs_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_dbs); +} +__exitcall(cpufreq_gov_dbs_exit); + void __init cpufreq_cmdline_parse(char *str) { do { |