aboutsummaryrefslogtreecommitdiffstats
path: root/xen/drivers/cpufreq
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-12-10 13:27:14 +0000
committerKeir Fraser <keir.fraser@citrix.com>2008-12-10 13:27:14 +0000
commit630b6713472007f100b40bf100246ca169b23a14 (patch)
tree70af1436ba366fc704e0b770fb11ae70c91145a7 /xen/drivers/cpufreq
parentac677794d61dc7a6f92b16946863043da890c828 (diff)
downloadxen-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/Makefile1
-rw-r--r--xen/drivers/cpufreq/cpufreq.c48
-rw-r--r--xen/drivers/cpufreq/cpufreq_misc_governors.c158
-rw-r--r--xen/drivers/cpufreq/cpufreq_ondemand.c12
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 {