|
|
Log in / Subscribe / Register

3/3 A dynamic cpufreq governor

From:  "Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com>
To:  <linux-kernel@vger.kernel.org>, <cpufreq@www.linux.org.uk>, "Linus Torvalds" <torvalds@osdl.org>, <akpm@osdl.org>
Subject:  [PATCH] 3/3 A dynamic cpufreq governor
Date:  Sat, 25 Oct 2003 12:55:10 -0700
Cc:  "Pavel Machek" <pavel@ucw.cz>, "Dominik Brodowski" <linux@brodo.de>, "Nakajima, Jun" <jun.nakajima@intel.com>

ondemand3.patch - Adding sysfs interface for cpufreq_ondemand 
tunables and making sysfs access by cpufreq governors safe against 
removal of the underlying module (from Dominik). 

diffstat ondemand3.patch
 cpufreq.c          |   24 ++++++++++++
 cpufreq_ondemand.c |  102
+++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 126 insertions(+)



diff -purN linux-2.6.0-test8/drivers/cpufreq/cpufreq.c
linux-2.6.0-test8-dbs/drivers/cpufreq/cpufreq.c
--- linux-2.6.0-test8/drivers/cpufreq/cpufreq.c	2003-10-17
14:42:56.000000000 -0700
+++ linux-2.6.0-test8-dbs/drivers/cpufreq/cpufreq.c	2003-10-25
13:40:19.000000000 -0700
@@ -98,6 +98,24 @@ static void cpufreq_cpu_put(struct cpufr
 	module_put(cpufreq_driver->owner);
 }
 
+
+static unsigned int governor_get(struct cpufreq_policy *data)
+{
+	if (cpufreq_driver->setpolicy)
+		return 1;
+	if (try_module_get(data->governor->owner))
+		return 1;
+	return 0;
+}
+
+
+static void governor_put(struct cpufreq_policy *data)
+{
+	if (cpufreq_driver->target)
+		module_put(data->governor->owner);
+}
+
+
 /*********************************************************************
  *                          SYSFS INTERFACE                          *
  *********************************************************************/
@@ -305,7 +323,10 @@ static ssize_t show(struct kobject * kob
 	policy = cpufreq_cpu_get(policy->cpu);
 	if (!policy)
 		return -EINVAL;
+	if (!governor_get(policy))
+		return -EINVAL;
 	ret = fattr->show ? fattr->show(policy,buf) : 0;
+	governor_put(policy);
 	cpufreq_cpu_put(policy);
 	return ret;
 }
@@ -319,7 +340,10 @@ static ssize_t store(struct kobject * ko
 	policy = cpufreq_cpu_get(policy->cpu);
 	if (!policy)
 		return -EINVAL;
+	if (!governor_get(policy))
+		return -EINVAL;
 	ret = fattr->store ? fattr->store(policy,buf,count) : 0;
+	governor_put(policy);
 	cpufreq_cpu_put(policy);
 	return ret;
 }
diff -purN linux-2.6.0-test8/drivers/cpufreq/cpufreq_ondemand.c
linux-2.6.0-test8-dbs/drivers/cpufreq/cpufreq_ondemand.c
--- linux-2.6.0-test8/drivers/cpufreq/cpufreq_ondemand.c
2003-10-25 13:45:59.000000000 -0700
+++ linux-2.6.0-test8-dbs/drivers/cpufreq/cpufreq_ondemand.c
2003-10-25 13:44:40.000000000 -0700
@@ -73,6 +73,106 @@ struct dbs_tuners dbs_tuners_ins = {
 	.down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
 };
 
+/************************** sysfs interface ************************/
+static ssize_t show_current_freq(struct cpufreq_policy *policy, char
*buf)
+{
+	return sprintf (buf, "%u\n", policy->cur);
+}
+
+static struct freq_attr current_freq = {
+	.attr = { .name = "current_freq", .mode = 0444 },
+	.show = show_current_freq,
+};
+
+/* cpufreq_ondemand Governor Tunables */
+#define show_one(file_name, object)
\
+static ssize_t show_##file_name
\
+(struct cpufreq_policy *unused, char *buf)
\
+{
\
+	return sprintf(buf, "%u\n", dbs_tuners_ins.object);
\
+}
+show_one(sampling_rate, sampling_rate);
+show_one(up_threshold, up_threshold);
+show_one(down_threshold, down_threshold);
+
+static ssize_t store_sampling_rate(struct cpufreq_policy *unused, 
+		const char *buf, size_t count)
+{
+	unsigned int input;
+	int ret;
+	ret = sscanf (buf, "%u", &input);
+	down(&dbs_sem);
+	if (ret != 1 || input > MAX_SAMPLING_RATE || input <
MIN_SAMPLING_RATE)
+		goto out;
+
+	dbs_tuners_ins.sampling_rate = input;
+out:
+	up(&dbs_sem);
+	return count;
+}
+
+static ssize_t store_up_threshold(struct cpufreq_policy *unused, 
+		const char *buf, size_t count)
+{
+	unsigned int input;
+	int ret;
+	ret = sscanf (buf, "%u", &input);
+	down(&dbs_sem);
+	if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || 
+			input < MIN_FREQUENCY_UP_THRESHOLD ||
+			input <= dbs_tuners_ins.down_threshold)
+		goto out;
+
+	dbs_tuners_ins.up_threshold = input;
+out:
+	up(&dbs_sem);
+	return count;
+}
+
+static ssize_t store_down_threshold(struct cpufreq_policy *unused, 
+		const char *buf, size_t count)
+{
+	unsigned int input;
+	int ret;
+	ret = sscanf (buf, "%u", &input);
+	down(&dbs_sem);
+	if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD || 
+			input < MIN_FREQUENCY_DOWN_THRESHOLD ||
+			input >= dbs_tuners_ins.up_threshold)
+		goto out;
+
+	dbs_tuners_ins.down_threshold = input;
+out:
+	up(&dbs_sem);
+	return count;
+}
+
+#define define_one_rw(_name) 					\
+static struct freq_attr _name = {
\
+	.attr = { .name = __stringify(_name), .mode = 0644 }, 	\
+	.show = show_##_name, 					\
+	.store = store_##_name, 				\
+}
+
+define_one_rw(sampling_rate);
+define_one_rw(up_threshold);
+define_one_rw(down_threshold);
+
+static struct attribute * dbs_attributes[] = {
+	&current_freq.attr,
+	&sampling_rate.attr,
+	&up_threshold.attr,
+	&down_threshold.attr,
+	NULL
+};
+
+static struct attribute_group dbs_attr_group = {
+	.attrs = dbs_attributes,
+	.name = "ondemand",
+};
+
+/************************** sysfs end ************************/
+
 static void dbs_check_cpu(int cpu)
 {
 	unsigned int idle_ticks, up_idle_ticks, down_idle_ticks;
@@ -160,6 +260,7 @@ static int cpufreq_governor_dbs(struct c
 		cpu_dbs_info[cpu].prev_cpu_idle = 
 				kstat_cpu(cpu).cpustat.idle;
 		cpu_dbs_info[cpu].enable = 1;
+		sysfs_create_group(&policy->kobj, &dbs_attr_group);
 		dbs_enable++;
 		/*
 		 * Start the timerschedule work, when this governor
@@ -177,6 +278,7 @@ static int cpufreq_governor_dbs(struct c
 			policy->cpu, policy->max, policy->min,
policy->cur);
 		down(&dbs_sem);
 		cpu_dbs_info[cpu].enable = 0;
+		sysfs_remove_group(&policy->kobj, &dbs_attr_group);
 		dbs_enable--;
 		/*
 		 * Stop the timerschedule work, when this governor


Copyright © 2003, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds