aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Jones <davej@delerium.kernelslacker.org>2005-01-14 06:17:42 -0500
committerDave Jones <davej@delerium.kernelslacker.org>2005-01-14 06:17:42 -0500
commitba420e2869fdcf4b917bb4d53a39ad67b84223e3 (patch)
tree9a3eed09bcf08f0eb3d63d8c39dd35672f6d016e /drivers
parent812ab7f31be1ebce3afdd3209c08b596903a9bef (diff)
parentc24a8e84587b96d45ae534546027087e8a62ba1e (diff)
downloadhistory-ba420e2869fdcf4b917bb4d53a39ad67b84223e3.tar.gz
Merge delerium.kernelslacker.org:/mnt/data/src/bk/bk-linus
into delerium.kernelslacker.org:/mnt/data/src/bk/cpufreq
Diffstat (limited to 'drivers')
-rw-r--r--drivers/cpufreq/Kconfig41
-rw-r--r--drivers/cpufreq/Makefile3
-rw-r--r--drivers/cpufreq/cpufreq.c20
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c80
-rw-r--r--drivers/cpufreq/cpufreq_stats.c334
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c400
-rw-r--r--drivers/cpufreq/freq_table.c5
-rw-r--r--drivers/cpufreq/proc_intf.c263
8 files changed, 442 insertions, 704 deletions
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index aa8eaca6e2eaf0..ffe3d0439d8684 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -27,17 +27,21 @@ config CPU_FREQ_DEBUG
2 to activate CPUfreq drivers debugging, and
4 to activate CPUfreq governor debugging
-config CPU_FREQ_PROC_INTF
- tristate "/proc/cpufreq interface (deprecated)"
- depends on CPU_FREQ && PROC_FS
- help
- This enables the /proc/cpufreq interface for controlling
- CPUFreq. Please note that it is recommended to use the sysfs
- interface instead (which is built automatically).
-
- For details, take a look at <file:Documentation/cpu-freq/>.
-
- If in doubt, say N.
+config CPU_FREQ_STAT
+ tristate "CPU frequency translation statistics"
+ depends on CPU_FREQ && CPU_FREQ_TABLE
+ default y
+ help
+ This driver exports CPU frequency statistics information through sysfs
+ file system
+
+config CPU_FREQ_STAT_DETAILS
+ bool "CPU frequency translation statistics details"
+ depends on CPU_FREQ && CPU_FREQ_STAT
+ default n
+ help
+ This will show detail CPU frequency translation table in sysfs file
+ system
choice
prompt "Default CPUFreq governor"
@@ -98,21 +102,6 @@ config CPU_FREQ_GOV_USERSPACE
If in doubt, say Y.
-config CPU_FREQ_24_API
- bool "/proc/sys/cpu/ interface (2.4. / OLD)"
- depends on CPU_FREQ_GOV_USERSPACE
- depends on SYSCTL
- help
- This enables the /proc/sys/cpu/ sysctl interface for controlling
- the CPUFreq,"userspace" governor. This is the same interface
- as known from the 2.4.-kernel patches for CPUFreq, and offers
- the same functionality as long as "userspace" is the
- selected governor for the specified CPU.
-
- For details, take a look at <file:Documentation/cpu-freq/>.
-
- If in doubt, say N.
-
config CPU_FREQ_GOV_ONDEMAND
tristate "'ondemand' cpufreq policy governor"
depends on CPU_FREQ
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 50291abb48637a..67b16e5a41a790 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -1,5 +1,7 @@
# CPUfreq core
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
+# CPUfreq stats
+obj-$(CONFIG_CPU_FREQ_STAT) += cpufreq_stats.o
# CPUfreq governors
obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o
@@ -9,5 +11,4 @@ obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o
# CPUfreq cross-arch helpers
obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
-obj-$(CONFIG_CPU_FREQ_PROC_INTF) += proc_intf.o
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index c2de232af96643..30d9c6a87a0e1d 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -63,7 +63,7 @@ static DECLARE_RWSEM (cpufreq_notifier_rwsem);
static LIST_HEAD(cpufreq_governor_list);
static DECLARE_MUTEX (cpufreq_governor_sem);
-static struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
+struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
{
struct cpufreq_policy *data;
unsigned long flags;
@@ -102,12 +102,14 @@ static struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
err_out:
return NULL;
}
+EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
-static void cpufreq_cpu_put(struct cpufreq_policy *data)
+void cpufreq_cpu_put(struct cpufreq_policy *data)
{
kobject_put(&data->kobj);
module_put(cpufreq_driver->owner);
}
+EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
/*********************************************************************
@@ -285,7 +287,7 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
/**
* cpufreq_parse_governor - parse a governor string
*/
-int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
+static int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
struct cpufreq_governor **governor)
{
if (!cpufreq_driver)
@@ -763,8 +765,11 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
#endif
+ down(&data->lock);
if (cpufreq_driver->target)
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
+ cpufreq_driver->target = NULL;
+ up(&data->lock);
kobject_unregister(&data->kobj);
@@ -893,6 +898,13 @@ static int cpufreq_resume(struct sys_device * sysdev)
return 0;
}
+ if (cpufreq_driver->resume) {
+ ret = cpufreq_driver->resume(cpu_policy);
+ printk(KERN_ERR "cpufreq: resume failed in ->resume step on CPU %u\n", cpu_policy->cpu);
+ cpufreq_cpu_put(cpu_policy);
+ return (ret);
+ }
+
if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
unsigned int cur_freq = 0;
@@ -1018,7 +1030,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
lock_cpu_hotplug();
dprintk("target for CPU %u: %u kHz, relation %u\n", policy->cpu,
target_freq, relation);
- if (cpu_online(policy->cpu))
+ if (cpu_online(policy->cpu) && cpufreq_driver->target)
retval = cpufreq_driver->target(policy, target_freq, relation);
unlock_cpu_hotplug();
return retval;
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index bc31cac09a204b..8d83a21c6477f3 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -229,10 +229,14 @@ static void dbs_check_cpu(int cpu)
static int down_skip[NR_CPUS];
struct cpu_dbs_info_s *this_dbs_info;
+ struct cpufreq_policy *policy;
+ unsigned int j;
+
this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
if (!this_dbs_info->enable)
return;
+ policy = this_dbs_info->cur_policy;
/*
* The default safe range is 20% to 80%
* Every sampling_rate, we check
@@ -246,12 +250,33 @@ static void dbs_check_cpu(int cpu)
* Frequency reduction happens at minimum steps of
* 5% of max_frequency
*/
+
/* Check for frequency increase */
total_idle_ticks = kstat_cpu(cpu).cpustat.idle +
kstat_cpu(cpu).cpustat.iowait;
idle_ticks = total_idle_ticks -
this_dbs_info->prev_cpu_idle_up;
this_dbs_info->prev_cpu_idle_up = total_idle_ticks;
+
+
+ for_each_cpu_mask(j, policy->cpus) {
+ unsigned int tmp_idle_ticks;
+ struct cpu_dbs_info_s *j_dbs_info;
+
+ if (j == cpu)
+ continue;
+
+ j_dbs_info = &per_cpu(cpu_dbs_info, j);
+ /* Check for frequency increase */
+ total_idle_ticks = kstat_cpu(j).cpustat.idle +
+ kstat_cpu(j).cpustat.iowait;
+ tmp_idle_ticks = total_idle_ticks -
+ j_dbs_info->prev_cpu_idle_up;
+ j_dbs_info->prev_cpu_idle_up = total_idle_ticks;
+
+ if (tmp_idle_ticks < idle_ticks)
+ idle_ticks = tmp_idle_ticks;
+ }
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks *= 100;
@@ -259,8 +284,7 @@ static void dbs_check_cpu(int cpu)
sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate);
if (idle_ticks < up_idle_ticks) {
- __cpufreq_driver_target(this_dbs_info->cur_policy,
- this_dbs_info->cur_policy->max,
+ __cpufreq_driver_target(policy, policy->max,
CPUFREQ_RELATION_H);
down_skip[cpu] = 0;
this_dbs_info->prev_cpu_idle_down = total_idle_ticks;
@@ -272,12 +296,34 @@ static void dbs_check_cpu(int cpu)
if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor)
return;
+ total_idle_ticks = kstat_cpu(cpu).cpustat.idle +
+ kstat_cpu(cpu).cpustat.iowait;
idle_ticks = total_idle_ticks -
this_dbs_info->prev_cpu_idle_down;
+ this_dbs_info->prev_cpu_idle_down = total_idle_ticks;
+
+ for_each_cpu_mask(j, policy->cpus) {
+ unsigned int tmp_idle_ticks;
+ struct cpu_dbs_info_s *j_dbs_info;
+
+ if (j == cpu)
+ continue;
+
+ j_dbs_info = &per_cpu(cpu_dbs_info, j);
+ /* Check for frequency increase */
+ total_idle_ticks = kstat_cpu(j).cpustat.idle +
+ kstat_cpu(j).cpustat.iowait;
+ tmp_idle_ticks = total_idle_ticks -
+ j_dbs_info->prev_cpu_idle_down;
+ j_dbs_info->prev_cpu_idle_down = total_idle_ticks;
+
+ if (tmp_idle_ticks < idle_ticks)
+ idle_ticks = tmp_idle_ticks;
+ }
+
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks *= 100;
down_skip[cpu] = 0;
- this_dbs_info->prev_cpu_idle_down = total_idle_ticks;
freq_down_sampling_rate = dbs_tuners_ins.sampling_rate *
dbs_tuners_ins.sampling_down_factor;
@@ -285,14 +331,14 @@ static void dbs_check_cpu(int cpu)
sampling_rate_in_HZ(freq_down_sampling_rate);
if (idle_ticks > down_idle_ticks ) {
- freq_down_step = (5 * this_dbs_info->cur_policy->max) / 100;
+ freq_down_step = (5 * policy->max) / 100;
/* max freq cannot be less than 100. But who knows.... */
if (unlikely(freq_down_step == 0))
freq_down_step = 5;
- __cpufreq_driver_target(this_dbs_info->cur_policy,
- this_dbs_info->cur_policy->cur - freq_down_step,
+ __cpufreq_driver_target(policy,
+ policy->cur - freq_down_step,
CPUFREQ_RELATION_H);
return;
}
@@ -313,7 +359,8 @@ static void do_dbs_timer(void *data)
static inline void dbs_timer_init(void)
{
INIT_WORK(&dbs_work, do_dbs_timer, NULL);
- schedule_work(&dbs_work);
+ schedule_delayed_work(&dbs_work,
+ sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate));
return;
}
@@ -328,6 +375,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
{
unsigned int cpu = policy->cpu;
struct cpu_dbs_info_s *this_dbs_info;
+ unsigned int j;
this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
@@ -344,14 +392,18 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
break;
down(&dbs_sem);
- this_dbs_info->cur_policy = policy;
+ for_each_cpu_mask(j, policy->cpus) {
+ struct cpu_dbs_info_s *j_dbs_info;
+ j_dbs_info = &per_cpu(cpu_dbs_info, j);
+ j_dbs_info->cur_policy = policy;
- this_dbs_info->prev_cpu_idle_up =
- kstat_cpu(cpu).cpustat.idle +
- kstat_cpu(cpu).cpustat.iowait;
- this_dbs_info->prev_cpu_idle_down =
- kstat_cpu(cpu).cpustat.idle +
- kstat_cpu(cpu).cpustat.iowait;
+ j_dbs_info->prev_cpu_idle_up =
+ kstat_cpu(j).cpustat.idle +
+ kstat_cpu(j).cpustat.iowait;
+ j_dbs_info->prev_cpu_idle_down =
+ kstat_cpu(j).cpustat.idle +
+ kstat_cpu(j).cpustat.iowait;
+ }
this_dbs_info->enable = 1;
sysfs_create_group(&policy->kobj, &dbs_attr_group);
dbs_enable++;
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
new file mode 100644
index 00000000000000..2084593937c638
--- /dev/null
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -0,0 +1,334 @@
+/*
+ * drivers/cpufreq/cpufreq_stats.c
+ *
+ * Copyright (C) 2003-2004 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
+ * (C) 2004 Zou Nan hai <nanhai.zou@intel.com>.
+ *
+ * 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 <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
+#include <linux/sysfs.h>
+#include <linux/cpufreq.h>
+#include <linux/jiffies.h>
+#include <linux/percpu.h>
+#include <linux/kobject.h>
+#include <linux/spinlock.h>
+
+static spinlock_t cpufreq_stats_lock;
+
+#define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \
+static struct freq_attr _attr_##_name = {\
+ .attr = {.name = __stringify(_name), .owner = THIS_MODULE, \
+ .mode = _mode, }, \
+ .show = _show,\
+};
+
+static unsigned long
+delta_time(unsigned long old, unsigned long new)
+{
+ return (old > new) ? (old - new): (new + ~old + 1);
+}
+
+struct cpufreq_stats {
+ unsigned int cpu;
+ unsigned int total_trans;
+ unsigned long long last_time;
+ unsigned int max_state;
+ unsigned int state_num;
+ unsigned int last_index;
+ unsigned long long *time_in_state;
+ unsigned int *freq_table;
+#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
+ unsigned int *trans_table;
+#endif
+};
+
+static struct cpufreq_stats *cpufreq_stats_table[NR_CPUS];
+
+struct cpufreq_stats_attribute {
+ struct attribute attr;
+ ssize_t(*show) (struct cpufreq_stats *, char *);
+};
+
+static int
+cpufreq_stats_update (unsigned int cpu)
+{
+ struct cpufreq_stats *stat;
+ spin_lock(&cpufreq_stats_lock);
+ stat = cpufreq_stats_table[cpu];
+ if (stat->time_in_state)
+ stat->time_in_state[stat->last_index] +=
+ delta_time(stat->last_time, jiffies);
+ stat->last_time = jiffies;
+ spin_unlock(&cpufreq_stats_lock);
+ return 0;
+}
+
+static ssize_t
+show_total_trans(struct cpufreq_policy *policy, char *buf)
+{
+ struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
+ if(!stat)
+ return 0;
+ return sprintf(buf, "%d\n",
+ cpufreq_stats_table[stat->cpu]->total_trans);
+}
+
+static ssize_t
+show_time_in_state(struct cpufreq_policy *policy, char *buf)
+{
+ ssize_t len = 0;
+ int i;
+ struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
+ if(!stat)
+ return 0;
+ cpufreq_stats_update(stat->cpu);
+ for (i = 0; i < stat->state_num; i++) {
+ len += sprintf(buf + len, "%u %llu\n",
+ stat->freq_table[i], stat->time_in_state[i]);
+ }
+ return len;
+}
+
+#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
+static ssize_t
+show_trans_table(struct cpufreq_policy *policy, char *buf)
+{
+ ssize_t len = 0;
+ int i, j;
+
+ struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
+ if(!stat)
+ return 0;
+ cpufreq_stats_update(stat->cpu);
+ for (i = 0; i < stat->state_num; i++) {
+ if (len >= PAGE_SIZE)
+ break;
+ len += snprintf(buf + len, PAGE_SIZE - len, "%9u:\t",
+ stat->freq_table[i]);
+
+ for (j = 0; j < stat->state_num; j++) {
+ if (len >= PAGE_SIZE)
+ break;
+ len += snprintf(buf + len, PAGE_SIZE - len, "%u\t",
+ stat->trans_table[i*stat->max_state+j]);
+ }
+ len += snprintf(buf + len, PAGE_SIZE - len, "\n");
+ }
+ return len;
+}
+CPUFREQ_STATDEVICE_ATTR(trans_table,0444,show_trans_table);
+#endif
+
+CPUFREQ_STATDEVICE_ATTR(total_trans,0444,show_total_trans);
+CPUFREQ_STATDEVICE_ATTR(time_in_state,0444,show_time_in_state);
+
+static struct attribute *default_attrs[] = {
+ &_attr_total_trans.attr,
+ &_attr_time_in_state.attr,
+#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
+ &_attr_trans_table.attr,
+#endif
+ NULL
+};
+static struct attribute_group stats_attr_group = {
+ .attrs = default_attrs,
+ .name = "stats"
+};
+
+static int
+freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
+{
+ int index;
+ for (index = 0; index < stat->max_state; index++)
+ if (stat->freq_table[index] == freq)
+ return index;
+ return -1;
+}
+
+static void
+cpufreq_stats_free_table (unsigned int cpu)
+{
+ struct cpufreq_stats *stat = cpufreq_stats_table[cpu];
+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+ if (policy && policy->cpu == cpu)
+ sysfs_remove_group(&policy->kobj, &stats_attr_group);
+ if (stat) {
+ kfree(stat->time_in_state);
+ kfree(stat);
+ }
+ cpufreq_stats_table[cpu] = NULL;
+ if (policy)
+ cpufreq_cpu_put(policy);
+}
+
+static int
+cpufreq_stats_create_table (struct cpufreq_policy *policy,
+ struct cpufreq_frequency_table *table)
+{
+ unsigned int i, j, count = 0, ret = 0;
+ struct cpufreq_stats *stat;
+ struct cpufreq_policy *data;
+ unsigned int alloc_size;
+ unsigned int cpu = policy->cpu;
+ if (cpufreq_stats_table[cpu])
+ return -EBUSY;
+ if ((stat = kmalloc(sizeof(struct cpufreq_stats), GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+ memset(stat, 0, sizeof (struct cpufreq_stats));
+
+ data = cpufreq_cpu_get(cpu);
+ if ((ret = sysfs_create_group(&data->kobj, &stats_attr_group)))
+ goto error_out;
+
+ stat->cpu = cpu;
+ cpufreq_stats_table[cpu] = stat;
+
+ for (i=0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
+ unsigned int freq = table[i].frequency;
+ if (freq == CPUFREQ_ENTRY_INVALID)
+ continue;
+ count++;
+ }
+
+ alloc_size = count * sizeof(int) + count * sizeof(long long);
+
+#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
+ alloc_size += count * count * sizeof(int);
+#endif
+ stat->max_state = count;
+ stat->time_in_state = kmalloc(alloc_size, GFP_KERNEL);
+ if (!stat->time_in_state) {
+ ret = -ENOMEM;
+ goto error_out;
+ }
+ memset(stat->time_in_state, 0, alloc_size);
+ stat->freq_table = (unsigned int *)(stat->time_in_state + count);
+
+#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
+ stat->trans_table = stat->freq_table + count;
+#endif
+ j = 0;
+ for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
+ unsigned int freq = table[i].frequency;
+ if (freq == CPUFREQ_ENTRY_INVALID)
+ continue;
+ if (freq_table_get_index(stat, freq) == -1)
+ stat->freq_table[j++] = freq;
+ }
+ stat->state_num = j;
+ spin_lock(&cpufreq_stats_lock);
+ stat->last_time = jiffies;
+ stat->last_index = freq_table_get_index(stat, policy->cur);
+ spin_unlock(&cpufreq_stats_lock);
+ cpufreq_cpu_put(data);
+ return 0;
+error_out:
+ cpufreq_cpu_put(data);
+ kfree(stat);
+ cpufreq_stats_table[cpu] = NULL;
+ return ret;
+}
+
+static int
+cpufreq_stat_notifier_policy (struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ int ret;
+ struct cpufreq_policy *policy = data;
+ struct cpufreq_frequency_table *table;
+ unsigned int cpu = policy->cpu;
+ if (val != CPUFREQ_NOTIFY)
+ return 0;
+ table = cpufreq_frequency_get_table(cpu);
+ if (!table)
+ return 0;
+ if ((ret = cpufreq_stats_create_table(policy, table)))
+ return ret;
+ return 0;
+}
+
+static int
+cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ struct cpufreq_freqs *freq = data;
+ struct cpufreq_stats *stat;
+ int old_index, new_index;
+
+ if (val != CPUFREQ_POSTCHANGE)
+ return 0;
+
+ stat = cpufreq_stats_table[freq->cpu];
+ if (!stat)
+ return 0;
+ old_index = freq_table_get_index(stat, freq->old);
+ new_index = freq_table_get_index(stat, freq->new);
+
+ cpufreq_stats_update(freq->cpu);
+ if (old_index == new_index)
+ return 0;
+
+ spin_lock(&cpufreq_stats_lock);
+ stat->last_index = new_index;
+#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
+ stat->trans_table[old_index * stat->max_state + new_index]++;
+#endif
+ stat->total_trans++;
+ spin_unlock(&cpufreq_stats_lock);
+ return 0;
+}
+
+static struct notifier_block notifier_policy_block = {
+ .notifier_call = cpufreq_stat_notifier_policy
+};
+
+static struct notifier_block notifier_trans_block = {
+ .notifier_call = cpufreq_stat_notifier_trans
+};
+
+static int
+__init cpufreq_stats_init(void)
+{
+ int ret;
+ unsigned int cpu;
+ spin_lock_init(&cpufreq_stats_lock);
+ if ((ret = cpufreq_register_notifier(&notifier_policy_block,
+ CPUFREQ_POLICY_NOTIFIER)))
+ return ret;
+
+ if ((ret = cpufreq_register_notifier(&notifier_trans_block,
+ CPUFREQ_TRANSITION_NOTIFIER))) {
+ cpufreq_unregister_notifier(&notifier_policy_block,
+ CPUFREQ_POLICY_NOTIFIER);
+ return ret;
+ }
+
+ for_each_cpu(cpu)
+ cpufreq_update_policy(cpu);
+ return 0;
+}
+static void
+__exit cpufreq_stats_exit(void)
+{
+ unsigned int cpu;
+ cpufreq_unregister_notifier(&notifier_policy_block,
+ CPUFREQ_POLICY_NOTIFIER);
+ cpufreq_unregister_notifier(&notifier_trans_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+ for_each_cpu(cpu)
+ cpufreq_stats_free_table(cpu);
+}
+
+MODULE_AUTHOR ("Zou Nan hai <nanhai.zou@intel.com>");
+MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats through sysfs filesystem");
+MODULE_LICENSE ("GPL");
+
+module_init(cpufreq_stats_init);
+module_exit(cpufreq_stats_exit);
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index cf107b0526521a..d32bf3593cd314 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -17,51 +17,13 @@
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
-#include <linux/ctype.h>
#include <linux/cpufreq.h>
-#include <linux/sysctl.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/sysfs.h>
#include <asm/uaccess.h>
-#define CTL_CPU_VARS_SPEED_MAX(cpunr) { \
- .ctl_name = CPU_NR_FREQ_MAX, \
- .data = &cpu_max_freq[cpunr], \
- .procname = "speed-max", \
- .maxlen = sizeof(cpu_max_freq[cpunr]),\
- .mode = 0444, \
- .proc_handler = proc_dointvec, }
-
-#define CTL_CPU_VARS_SPEED_MIN(cpunr) { \
- .ctl_name = CPU_NR_FREQ_MIN, \
- .data = &cpu_min_freq[cpunr], \
- .procname = "speed-min", \
- .maxlen = sizeof(cpu_min_freq[cpunr]),\
- .mode = 0444, \
- .proc_handler = proc_dointvec, }
-
-#define CTL_CPU_VARS_SPEED(cpunr) { \
- .ctl_name = CPU_NR_FREQ, \
- .procname = "speed", \
- .mode = 0644, \
- .proc_handler = cpufreq_procctl, \
- .strategy = cpufreq_sysctl, \
- .extra1 = (void*) (cpunr), }
-
-#define CTL_TABLE_CPU_VARS(cpunr) static ctl_table ctl_cpu_vars_##cpunr[] = {\
- CTL_CPU_VARS_SPEED_MAX(cpunr), \
- CTL_CPU_VARS_SPEED_MIN(cpunr), \
- CTL_CPU_VARS_SPEED(cpunr), \
- { .ctl_name = 0, }, }
-
-/* the ctl_table entry for each CPU */
-#define CPU_ENUM(s) { \
- .ctl_name = (CPU_NR + s), \
- .procname = #s, \
- .mode = 0555, \
- .child = ctl_cpu_vars_##s }
/**
* A few values needed by the userspace governor
@@ -96,17 +58,17 @@ static struct notifier_block userspace_cpufreq_notifier_block = {
/**
- * _cpufreq_set - set the CPU frequency
+ * cpufreq_set - set the CPU frequency
* @freq: target frequency in kHz
* @cpu: CPU for which the frequency is to be set
*
* Sets the CPU frequency to freq.
*/
-static int _cpufreq_set(unsigned int freq, unsigned int cpu)
+static int cpufreq_set(unsigned int freq, unsigned int cpu)
{
int ret = -EINVAL;
- dprintk("_cpufreq_set for cpu %u, freq %u kHz\n", cpu, freq);
+ dprintk("cpufreq_set for cpu %u, freq %u kHz\n", cpu, freq);
down(&userspace_sem);
if (!cpu_is_managed[cpu])
@@ -135,358 +97,6 @@ static int _cpufreq_set(unsigned int freq, unsigned int cpu)
}
-#ifdef CONFIG_CPU_FREQ_24_API
-
-#warning The /proc/sys/cpu/ and sysctl interface to cpufreq will be removed from the 2.6. kernel series soon after 2005-01-01
-
-static unsigned int warning_print = 0;
-
-int __deprecated cpufreq_set(unsigned int freq, unsigned int cpu)
-{
- return _cpufreq_set(freq, cpu);
-}
-EXPORT_SYMBOL_GPL(cpufreq_set);
-
-
-/**
- * cpufreq_setmax - set the CPU to the maximum frequency
- * @cpu - affected cpu;
- *
- * Sets the CPU frequency to the maximum frequency supported by
- * this CPU.
- */
-int __deprecated cpufreq_setmax(unsigned int cpu)
-{
- if (!cpu_is_managed[cpu] || !cpu_online(cpu))
- return -EINVAL;
- return _cpufreq_set(cpu_max_freq[cpu], cpu);
-}
-EXPORT_SYMBOL_GPL(cpufreq_setmax);
-
-/*********************** cpufreq_sysctl interface ********************/
-static int
-cpufreq_procctl(ctl_table *ctl, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos)
-{
- char buf[16], *p;
- int cpu = (long) ctl->extra1;
- unsigned int len, left = *lenp;
-
- if (!left || (*ppos && !write) || !cpu_online(cpu)) {
- *lenp = 0;
- return 0;
- }
-
- if (!warning_print) {
- warning_print++;
- printk(KERN_INFO "Access to /proc/sys/cpu/ is deprecated and "
- "will be removed from (new) 2.6. kernels soon "
- "after 2005-01-01\n");
- }
-
- if (write) {
- unsigned int freq;
-
- len = left;
- if (left > sizeof(buf))
- left = sizeof(buf);
- if (copy_from_user(buf, buffer, left))
- return -EFAULT;
- buf[sizeof(buf) - 1] = '\0';
-
- freq = simple_strtoul(buf, &p, 0);
- _cpufreq_set(freq, cpu);
- } else {
- len = sprintf(buf, "%d\n", cpufreq_get(cpu));
- if (len > left)
- len = left;
- if (copy_to_user(buffer, buf, len))
- return -EFAULT;
- }
-
- *lenp = len;
- *ppos += len;
- return 0;
-}
-
-static int
-cpufreq_sysctl(ctl_table *table, int __user *name, int nlen,
- void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context)
-{
- int cpu = (long) table->extra1;
-
- if (!cpu_online(cpu))
- return -EINVAL;
-
- if (!warning_print) {
- warning_print++;
- printk(KERN_INFO "Access to /proc/sys/cpu/ is deprecated and "
- "will be removed from (new) 2.6. kernels soon "
- "after 2005-01-01\n");
- }
-
- if (oldval && oldlenp) {
- size_t oldlen;
-
- if (get_user(oldlen, oldlenp))
- return -EFAULT;
-
- if (oldlen != sizeof(unsigned int))
- return -EINVAL;
-
- if (put_user(cpufreq_get(cpu), (unsigned int __user *)oldval) ||
- put_user(sizeof(unsigned int), oldlenp))
- return -EFAULT;
- }
- if (newval && newlen) {
- unsigned int freq;
-
- if (newlen != sizeof(unsigned int))
- return -EINVAL;
-
- if (get_user(freq, (unsigned int __user *)newval))
- return -EFAULT;
-
- _cpufreq_set(freq, cpu);
- }
- return 1;
-}
-
-/* ctl_table ctl_cpu_vars_{0,1,...,(NR_CPUS-1)} */
-/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */
- CTL_TABLE_CPU_VARS(0);
-#if NR_CPUS > 1
- CTL_TABLE_CPU_VARS(1);
-#endif
-#if NR_CPUS > 2
- CTL_TABLE_CPU_VARS(2);
-#endif
-#if NR_CPUS > 3
- CTL_TABLE_CPU_VARS(3);
-#endif
-#if NR_CPUS > 4
- CTL_TABLE_CPU_VARS(4);
-#endif
-#if NR_CPUS > 5
- CTL_TABLE_CPU_VARS(5);
-#endif
-#if NR_CPUS > 6
- CTL_TABLE_CPU_VARS(6);
-#endif
-#if NR_CPUS > 7
- CTL_TABLE_CPU_VARS(7);
-#endif
-#if NR_CPUS > 8
- CTL_TABLE_CPU_VARS(8);
-#endif
-#if NR_CPUS > 9
- CTL_TABLE_CPU_VARS(9);
-#endif
-#if NR_CPUS > 10
- CTL_TABLE_CPU_VARS(10);
-#endif
-#if NR_CPUS > 11
- CTL_TABLE_CPU_VARS(11);
-#endif
-#if NR_CPUS > 12
- CTL_TABLE_CPU_VARS(12);
-#endif
-#if NR_CPUS > 13
- CTL_TABLE_CPU_VARS(13);
-#endif
-#if NR_CPUS > 14
- CTL_TABLE_CPU_VARS(14);
-#endif
-#if NR_CPUS > 15
- CTL_TABLE_CPU_VARS(15);
-#endif
-#if NR_CPUS > 16
- CTL_TABLE_CPU_VARS(16);
-#endif
-#if NR_CPUS > 17
- CTL_TABLE_CPU_VARS(17);
-#endif
-#if NR_CPUS > 18
- CTL_TABLE_CPU_VARS(18);
-#endif
-#if NR_CPUS > 19
- CTL_TABLE_CPU_VARS(19);
-#endif
-#if NR_CPUS > 20
- CTL_TABLE_CPU_VARS(20);
-#endif
-#if NR_CPUS > 21
- CTL_TABLE_CPU_VARS(21);
-#endif
-#if NR_CPUS > 22
- CTL_TABLE_CPU_VARS(22);
-#endif
-#if NR_CPUS > 23
- CTL_TABLE_CPU_VARS(23);
-#endif
-#if NR_CPUS > 24
- CTL_TABLE_CPU_VARS(24);
-#endif
-#if NR_CPUS > 25
- CTL_TABLE_CPU_VARS(25);
-#endif
-#if NR_CPUS > 26
- CTL_TABLE_CPU_VARS(26);
-#endif
-#if NR_CPUS > 27
- CTL_TABLE_CPU_VARS(27);
-#endif
-#if NR_CPUS > 28
- CTL_TABLE_CPU_VARS(28);
-#endif
-#if NR_CPUS > 29
- CTL_TABLE_CPU_VARS(29);
-#endif
-#if NR_CPUS > 30
- CTL_TABLE_CPU_VARS(30);
-#endif
-#if NR_CPUS > 31
- CTL_TABLE_CPU_VARS(31);
-#endif
-#if NR_CPUS > 32
-#error please extend CPU enumeration
-#endif
-
-/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */
-static ctl_table ctl_cpu_table[NR_CPUS + 1] = {
- CPU_ENUM(0),
-#if NR_CPUS > 1
- CPU_ENUM(1),
-#endif
-#if NR_CPUS > 2
- CPU_ENUM(2),
-#endif
-#if NR_CPUS > 3
- CPU_ENUM(3),
-#endif
-#if NR_CPUS > 4
- CPU_ENUM(4),
-#endif
-#if NR_CPUS > 5
- CPU_ENUM(5),
-#endif
-#if NR_CPUS > 6
- CPU_ENUM(6),
-#endif
-#if NR_CPUS > 7
- CPU_ENUM(7),
-#endif
-#if NR_CPUS > 8
- CPU_ENUM(8),
-#endif
-#if NR_CPUS > 9
- CPU_ENUM(9),
-#endif
-#if NR_CPUS > 10
- CPU_ENUM(10),
-#endif
-#if NR_CPUS > 11
- CPU_ENUM(11),
-#endif
-#if NR_CPUS > 12
- CPU_ENUM(12),
-#endif
-#if NR_CPUS > 13
- CPU_ENUM(13),
-#endif
-#if NR_CPUS > 14
- CPU_ENUM(14),
-#endif
-#if NR_CPUS > 15
- CPU_ENUM(15),
-#endif
-#if NR_CPUS > 16
- CPU_ENUM(16),
-#endif
-#if NR_CPUS > 17
- CPU_ENUM(17),
-#endif
-#if NR_CPUS > 18
- CPU_ENUM(18),
-#endif
-#if NR_CPUS > 19
- CPU_ENUM(19),
-#endif
-#if NR_CPUS > 20
- CPU_ENUM(20),
-#endif
-#if NR_CPUS > 21
- CPU_ENUM(21),
-#endif
-#if NR_CPUS > 22
- CPU_ENUM(22),
-#endif
-#if NR_CPUS > 23
- CPU_ENUM(23),
-#endif
-#if NR_CPUS > 24
- CPU_ENUM(24),
-#endif
-#if NR_CPUS > 25
- CPU_ENUM(25),
-#endif
-#if NR_CPUS > 26
- CPU_ENUM(26),
-#endif
-#if NR_CPUS > 27
- CPU_ENUM(27),
-#endif
-#if NR_CPUS > 28
- CPU_ENUM(28),
-#endif
-#if NR_CPUS > 29
- CPU_ENUM(29),
-#endif
-#if NR_CPUS > 30
- CPU_ENUM(30),
-#endif
-#if NR_CPUS > 31
- CPU_ENUM(31),
-#endif
-#if NR_CPUS > 32
-#error please extend CPU enumeration
-#endif
- {
- .ctl_name = 0,
- }
-};
-
-static ctl_table ctl_cpu[2] = {
- {
- .ctl_name = CTL_CPU,
- .procname = "cpu",
- .mode = 0555,
- .child = ctl_cpu_table,
- },
- {
- .ctl_name = 0,
- }
-};
-
-static struct ctl_table_header *cpufreq_sysctl_table;
-
-static inline void cpufreq_sysctl_init(void)
-{
- cpufreq_sysctl_table = register_sysctl_table(ctl_cpu, 0);
-}
-
-static inline void cpufreq_sysctl_exit(void)
-{
- unregister_sysctl_table(cpufreq_sysctl_table);
-}
-
-#else
-#define cpufreq_sysctl_init() do {} while(0)
-#define cpufreq_sysctl_exit() do {} while(0)
-#endif /* CONFIG_CPU_FREQ_24API */
-
-
/************************** sysfs interface ************************/
static ssize_t show_speed (struct cpufreq_policy *policy, char *buf)
{
@@ -503,7 +113,7 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
if (ret != 1)
return -EINVAL;
- _cpufreq_set(freq, policy->cpu);
+ cpufreq_set(freq, policy->cpu);
return count;
}
@@ -577,7 +187,6 @@ EXPORT_SYMBOL(cpufreq_gov_userspace);
static int __init cpufreq_gov_userspace_init(void)
{
- cpufreq_sysctl_init();
cpufreq_register_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
return cpufreq_register_governor(&cpufreq_gov_userspace);
}
@@ -587,7 +196,6 @@ static void __exit cpufreq_gov_userspace_exit(void)
{
cpufreq_unregister_governor(&cpufreq_gov_userspace);
cpufreq_unregister_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
- cpufreq_sysctl_exit();
}
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 22e2ba6b14d4c8..ba460bdea60f60 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -214,6 +214,11 @@ void cpufreq_frequency_table_put_attr(unsigned int cpu)
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
+struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
+{
+ return show_table[cpu];
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
MODULE_DESCRIPTION ("CPUfreq frequency table helpers");
diff --git a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c
index 673977899e50d0..e69de29bb2d1d6 100644
--- a/drivers/cpufreq/proc_intf.c
+++ b/drivers/cpufreq/proc_intf.c
@@ -1,263 +0,0 @@
-/*
- * linux/drivers/cpufreq/proc_intf.c
- *
- * Copyright (C) 2002 - 2003 Dominik Brodowski
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/ctype.h>
-#include <linux/proc_fs.h>
-#include <asm/uaccess.h>
-
-#warning This module will be removed from the 2.6. kernel series soon after 2005-01-01
-
-#define CPUFREQ_ALL_CPUS ((NR_CPUS))
-
-static unsigned int warning_print = 0;
-
-/**
- * cpufreq_parse_policy - parse a policy string
- * @input_string: the string to parse.
- * @policy: the policy written inside input_string
- *
- * This function parses a "policy string" - something the user echo'es into
- * /proc/cpufreq or gives as boot parameter - into a struct cpufreq_policy.
- * If there are invalid/missing entries, they are replaced with current
- * cpufreq policy.
- */
-static int cpufreq_parse_policy(char input_string[42], struct cpufreq_policy *policy)
-{
- unsigned int min = 0;
- unsigned int max = 0;
- unsigned int cpu = 0;
- char str_governor[16];
- struct cpufreq_policy current_policy;
- unsigned int result = -EFAULT;
-
- if (!policy)
- return -EINVAL;
-
- policy->min = 0;
- policy->max = 0;
- policy->policy = 0;
- policy->cpu = CPUFREQ_ALL_CPUS;
-
- if (sscanf(input_string, "%d:%d:%d:%15s", &cpu, &min, &max, str_governor) == 4)
- {
- policy->min = min;
- policy->max = max;
- policy->cpu = cpu;
- result = 0;
- goto scan_policy;
- }
- if (sscanf(input_string, "%d%%%d%%%d%%%15s", &cpu, &min, &max, str_governor) == 4)
- {
- if (!cpufreq_get_policy(&current_policy, cpu)) {
- policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
- policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
- policy->cpu = cpu;
- result = 0;
- goto scan_policy;
- }
- }
-
- if (sscanf(input_string, "%d:%d:%15s", &min, &max, str_governor) == 3)
- {
- policy->min = min;
- policy->max = max;
- result = 0;
- goto scan_policy;
- }
-
- if (sscanf(input_string, "%d%%%d%%%15s", &min, &max, str_governor) == 3)
- {
- if (!cpufreq_get_policy(&current_policy, cpu)) {
- policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
- policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
- result = 0;
- goto scan_policy;
- }
- }
-
- return -EINVAL;
-
-scan_policy:
- result = cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor);
-
- return result;
-}
-
-/**
- * cpufreq_proc_read - read /proc/cpufreq
- *
- * This function prints out the current cpufreq policy.
- */
-static int cpufreq_proc_read (
- char *page,
- char **start,
- off_t off,
- int count,
- int *eof,
- void *data)
-{
- char *p = page;
- int len = 0;
- struct cpufreq_policy policy;
- unsigned int min_pctg = 0;
- unsigned int max_pctg = 0;
- unsigned int i = 0;
-
- if (off != 0)
- goto end;
-
- if (!warning_print) {
- warning_print++;
- printk(KERN_INFO "Access to /proc/cpufreq is deprecated and "
- "will be removed from (new) 2.6. kernels soon "
- "after 2005-01-01\n");
- }
-
- p += sprintf(p, " minimum CPU frequency - maximum CPU frequency - policy\n");
- for (i=0;i<NR_CPUS;i++) {
- if (!cpu_online(i))
- continue;
-
- if (cpufreq_get_policy(&policy, i))
- continue;
-
- if (!policy.cpuinfo.max_freq)
- continue;
-
- min_pctg = (policy.min * 100) / policy.cpuinfo.max_freq;
- max_pctg = (policy.max * 100) / policy.cpuinfo.max_freq;
-
- p += sprintf(p, "CPU%3d %9d kHz (%3d %%) - %9d kHz (%3d %%) - ",
- i , policy.min, min_pctg, policy.max, max_pctg);
- if (policy.policy) {
- switch (policy.policy) {
- case CPUFREQ_POLICY_POWERSAVE:
- p += sprintf(p, "powersave\n");
- break;
- case CPUFREQ_POLICY_PERFORMANCE:
- p += sprintf(p, "performance\n");
- break;
- default:
- p += sprintf(p, "INVALID\n");
- break;
- }
- } else
- p += scnprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name);
- }
-end:
- len = (p - page);
- if (len <= off+count)
- *eof = 1;
- *start = page + off;
- len -= off;
- if (len>count)
- len = count;
- if (len<0)
- len = 0;
-
- return len;
-}
-
-
-/**
- * cpufreq_proc_write - handles writing into /proc/cpufreq
- *
- * This function calls the parsing script and then sets the policy
- * accordingly.
- */
-static int cpufreq_proc_write (
- struct file *file,
- const char __user *buffer,
- unsigned long count,
- void *data)
-{
- int result = 0;
- char proc_string[42] = {'\0'};
- struct cpufreq_policy policy;
- unsigned int i = 0;
-
-
- if ((count > sizeof(proc_string) - 1))
- return -EINVAL;
-
- if (copy_from_user(proc_string, buffer, count))
- return -EFAULT;
-
- if (!warning_print) {
- warning_print++;
- printk(KERN_INFO "Access to /proc/cpufreq is deprecated and "
- "will be removed from (new) 2.6. kernels soon "
- "after 2005-01-01\n");
- }
-
- proc_string[count] = '\0';
-
- result = cpufreq_parse_policy(proc_string, &policy);
- if (result)
- return -EFAULT;
-
- if (policy.cpu == CPUFREQ_ALL_CPUS)
- {
- for (i=0; i<NR_CPUS; i++)
- {
- policy.cpu = i;
- if (cpu_online(i))
- cpufreq_set_policy(&policy);
- }
- }
- else
- cpufreq_set_policy(&policy);
-
- return count;
-}
-
-
-/**
- * cpufreq_proc_init - add "cpufreq" to the /proc root directory
- *
- * This function adds "cpufreq" to the /proc root directory.
- */
-static int __init cpufreq_proc_init (void)
-{
- struct proc_dir_entry *entry = NULL;
-
- /* are these acceptable values? */
- entry = create_proc_entry("cpufreq", S_IFREG|S_IRUGO|S_IWUSR,
- &proc_root);
-
- if (!entry) {
- printk(KERN_ERR "unable to create /proc/cpufreq entry\n");
- return -EIO;
- } else {
- entry->read_proc = cpufreq_proc_read;
- entry->write_proc = cpufreq_proc_write;
- }
-
- return 0;
-}
-
-
-/**
- * cpufreq_proc_exit - removes "cpufreq" from the /proc root directory.
- *
- * This function removes "cpufreq" from the /proc root directory.
- */
-static void __exit cpufreq_proc_exit (void)
-{
- remove_proc_entry("cpufreq", &proc_root);
- return;
-}
-
-MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
-MODULE_DESCRIPTION ("CPUfreq /proc/cpufreq interface");
-MODULE_LICENSE ("GPL");
-
-module_init(cpufreq_proc_init);
-module_exit(cpufreq_proc_exit);