diff options
author | Dave Jones <davej@delerium.kernelslacker.org> | 2005-01-14 06:17:42 -0500 |
---|---|---|
committer | Dave Jones <davej@delerium.kernelslacker.org> | 2005-01-14 06:17:42 -0500 |
commit | ba420e2869fdcf4b917bb4d53a39ad67b84223e3 (patch) | |
tree | 9a3eed09bcf08f0eb3d63d8c39dd35672f6d016e /drivers | |
parent | 812ab7f31be1ebce3afdd3209c08b596903a9bef (diff) | |
parent | c24a8e84587b96d45ae534546027087e8a62ba1e (diff) | |
download | history-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/Kconfig | 41 | ||||
-rw-r--r-- | drivers/cpufreq/Makefile | 3 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 20 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_ondemand.c | 80 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_stats.c | 334 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_userspace.c | 400 | ||||
-rw-r--r-- | drivers/cpufreq/freq_table.c | 5 | ||||
-rw-r--r-- | drivers/cpufreq/proc_intf.c | 263 |
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(¬ifier_policy_block, + CPUFREQ_POLICY_NOTIFIER))) + return ret; + + if ((ret = cpufreq_register_notifier(¬ifier_trans_block, + CPUFREQ_TRANSITION_NOTIFIER))) { + cpufreq_unregister_notifier(¬ifier_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(¬ifier_policy_block, + CPUFREQ_POLICY_NOTIFIER); + cpufreq_unregister_notifier(¬ifier_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(¤t_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(¤t_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); |