[PATCH] 3/3 A dynamic cpufreq governor

From: Pallipadi, Venkatesh
Date: Sat Oct 25 2003 - 14:59:34 EST


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

Attachment: ondemand3.patch
Description: ondemand3.patch