# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1228915634 0
# Node ID 9ba1541d6dc2d6c6e6c7cf0a57ef8a1f0ea9793d
# Parent b73f3646a17fa5fb9fa8edd0a5a4d70dd3353c15
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@xxxxxxxxx>
---
xen/drivers/cpufreq/Makefile | 1
xen/drivers/cpufreq/cpufreq.c | 48 ++++++++
xen/drivers/cpufreq/cpufreq_misc_governors.c | 158 +++++++++++++++++++++++++++
xen/drivers/cpufreq/cpufreq_ondemand.c | 12 ++
xen/include/acpi/cpufreq/cpufreq.h | 3
5 files changed, 222 insertions(+)
diff -r b73f3646a17f -r 9ba1541d6dc2 xen/drivers/cpufreq/Makefile
--- a/xen/drivers/cpufreq/Makefile Wed Dec 10 13:14:13 2008 +0000
+++ b/xen/drivers/cpufreq/Makefile Wed Dec 10 13:27:14 2008 +0000
@@ -1,3 +1,4 @@ obj-y += cpufreq.o
obj-y += cpufreq.o
obj-y += cpufreq_ondemand.o
+obj-y += cpufreq_misc_governors.o
obj-y += utility.o
diff -r b73f3646a17f -r 9ba1541d6dc2 xen/drivers/cpufreq/cpufreq.c
--- a/xen/drivers/cpufreq/cpufreq.c Wed Dec 10 13:14:13 2008 +0000
+++ b/xen/drivers/cpufreq/cpufreq.c Wed Dec 10 13:27:14 2008 +0000
@@ -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>
@@ -51,6 +52,53 @@ struct cpufreq_dom {
struct list_head node;
};
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)
{
diff -r b73f3646a17f -r 9ba1541d6dc2
xen/drivers/cpufreq/cpufreq_misc_governors.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/drivers/cpufreq/cpufreq_misc_governors.c Wed Dec 10 13:27:14
2008 +0000
@@ -0,0 +1,158 @@
+/*
+ * xen/drivers/cpufreq/cpufreq_misc_gov.c
+ *
+ * Copyright (C) 2001 Russell King
+ * (C) 2002 - 2004 Dominik Brodowski <linux@xxxxxxxx>
+ *
+ * Nov 2008 Liu Jinsong <jinsong.liu@xxxxxxxxx>
+ * 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 -r b73f3646a17f -r 9ba1541d6dc2 xen/drivers/cpufreq/cpufreq_ondemand.c
--- a/xen/drivers/cpufreq/cpufreq_ondemand.c Wed Dec 10 13:14:13 2008 +0000
+++ b/xen/drivers/cpufreq/cpufreq_ondemand.c Wed Dec 10 13:27:14 2008 +0000
@@ -262,6 +262,18 @@ struct cpufreq_governor cpufreq_gov_dbs
.name = "ondemand",
.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)
{
diff -r b73f3646a17f -r 9ba1541d6dc2 xen/include/acpi/cpufreq/cpufreq.h
--- a/xen/include/acpi/cpufreq/cpufreq.h Wed Dec 10 13:14:13 2008 +0000
+++ b/xen/include/acpi/cpufreq/cpufreq.h Wed Dec 10 13:27:14 2008 +0000
@@ -84,9 +84,12 @@ struct cpufreq_governor {
char name[CPUFREQ_NAME_LEN];
int (*governor)(struct cpufreq_policy *policy,
unsigned int event);
+ struct list_head governor_list;
};
extern struct cpufreq_governor cpufreq_gov_dbs;
+extern int cpufreq_register_governor(struct cpufreq_governor *governor);
+extern int cpufreq_unregister_governor(struct cpufreq_governor *governor);
#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_dbs
/* pass a target to the cpufreq driver */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|