Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Sat, 28 Sep 2002 05:30:53 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Sat, 28 Sep 2002 05:29:47 -0400 Received: from natwar.webmailer.de ([192.67.198.70]:61834 "EHLO post.webmailer.de") by vger.kernel.org with ESMTP id ; Sat, 28 Sep 2002 05:27:41 -0400 Date: Sat, 28 Sep 2002 11:27:13 +0200 From: Dominik Brodowski To: torvalds@transmeta.com, linux-kernel@vger.kernel.org Cc: hpa@zytor.com, cpufreq@www.linux.org.uk Subject: [2.5.39] (5/5) CPUfreq /proc/sys/cpu/ add-on patch Message-ID: <20020928112713.G1217@brodo.de> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.3.16i Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 14619 Lines: 642 CPUFreq 24-API add-on patch for 2.5.39: kernel/cpufreq.c cpufreq-24-API include/linux/cpufreq.h cpufreq-24-API arch/i386/config.in Transmeta LongRun does not work well with cpufreq-24-API arch/i386/Config.help help text for CONFIG_CPU_FREQ_24_API diff -ruN linux-2539original/arch/i386/Config.help linux/arch/i386/Config.help --- linux-2539original/arch/i386/Config.help Sun Sep 22 09:00:00 2002 +++ linux/arch/i386/Config.help Sat Sep 28 09:30:00 2002 @@ -850,6 +850,19 @@ If in doubt, say N. +CONFIG_CPU_FREQ_24_API + This enables the /proc/sys/cpu/ sysctl interface for controlling + CPUFreq, as known from the 2.4.-kernel patches for CPUFreq. Note + that some drivers do not support this interface or offer less + functionality. + + If you say N here, you'll be able to control CPUFreq using the + new /proc/cpufreq interface. + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say N. + CONFIG_X86_POWERNOW_K6 This adds the CPUFreq driver for mobile AMD K6-2+ and mobile AMD K6-3+ processors. diff -ruN linux-2539original/arch/i386/config.in linux/arch/i386/config.in --- linux-2539original/arch/i386/config.in Sun Sep 22 09:00:00 2002 +++ linux/arch/i386/config.in Sat Sep 28 09:30:00 2002 @@ -192,7 +192,10 @@ bool 'CPU Frequency scaling' CONFIG_CPU_FREQ if [ "$CONFIG_CPU_FREQ" = "y" ]; then - define_bool CONFIG_CPU_FREQ_26_API y + bool ' /proc/sys/cpu/ interface (2.4.)' CONFIG_CPU_FREQ_24_API + if [ "$CONFIG_CPU_FREQ_24_API" = "n" ]; then + define_bool CONFIG_CPU_FREQ_26_API y + fi tristate ' AMD Mobile K6-2/K6-3 PowerNow!' CONFIG_X86_POWERNOW_K6 if [ "$CONFIG_MELAN" = "y" ]; then tristate ' AMD Elan' CONFIG_ELAN_CPUFREQ @@ -200,7 +203,9 @@ tristate ' VIA Cyrix III Longhaul' CONFIG_X86_LONGHAUL tristate ' Intel Speedstep' CONFIG_X86_SPEEDSTEP tristate ' Intel Pentium 4 clock modulation' CONFIG_X86_P4_CLOCKMOD - tristate ' Transmeta LongRun' CONFIG_X86_LONGRUN + if [ "$CONFIG_CPU_FREQ_24_API" = "n" ]; then + tristate ' Transmeta LongRun' CONFIG_X86_LONGRUN + fi fi tristate 'Toshiba Laptop support' CONFIG_TOSHIBA diff -ruN linux-2539original/include/linux/cpufreq.h linux/include/linux/cpufreq.h --- linux-2539original/include/linux/cpufreq.h Sun Sep 22 09:00:00 2002 +++ linux/include/linux/cpufreq.h Sat Sep 28 09:30:00 2002 @@ -155,4 +155,98 @@ #endif +#ifdef CONFIG_CPU_FREQ_24_API +/********************************************************************* + * CPUFREQ 2.4. INTERFACE * + *********************************************************************/ +int cpufreq_setmax(unsigned int cpu); +#ifdef CONFIG_PM +int cpufreq_restore(void); +#endif +int cpufreq_set(unsigned int kHz, unsigned int cpu); +unsigned int cpufreq_get(unsigned int cpu); + +/* /proc/sys/cpu */ +enum { + CPU_NR = 1, /* compatibilty reasons */ + CPU_NR_0 = 1, + CPU_NR_1 = 2, + CPU_NR_2 = 3, + CPU_NR_3 = 4, + CPU_NR_4 = 5, + CPU_NR_5 = 6, + CPU_NR_6 = 7, + CPU_NR_7 = 8, + CPU_NR_8 = 9, + CPU_NR_9 = 10, + CPU_NR_10 = 11, + CPU_NR_11 = 12, + CPU_NR_12 = 13, + CPU_NR_13 = 14, + CPU_NR_14 = 15, + CPU_NR_15 = 16, + CPU_NR_16 = 17, + CPU_NR_17 = 18, + CPU_NR_18 = 19, + CPU_NR_19 = 20, + CPU_NR_20 = 21, + CPU_NR_21 = 22, + CPU_NR_22 = 23, + CPU_NR_23 = 24, + CPU_NR_24 = 25, + CPU_NR_25 = 26, + CPU_NR_26 = 27, + CPU_NR_27 = 28, + CPU_NR_28 = 29, + CPU_NR_29 = 30, + CPU_NR_30 = 31, + CPU_NR_31 = 32, +}; + +/* /proc/sys/cpu/{0,1,...,(NR_CPUS-1)} */ +enum { + CPU_NR_FREQ_MAX = 1, + CPU_NR_FREQ_MIN = 2, + CPU_NR_FREQ = 3, +}; + +#define CTL_CPU_VARS_SPEED_MAX { \ + ctl_name: CPU_NR_FREQ_MAX, \ + data: &cpu_max_freq, \ + procname: "speed-max", \ + maxlen: sizeof(cpu_max_freq),\ + mode: 0444, \ + proc_handler: proc_dointvec, } + +#define CTL_CPU_VARS_SPEED_MIN { \ + ctl_name: CPU_NR_FREQ_MIN, \ + data: &cpu_min_freq, \ + procname: "speed-min", \ + maxlen: sizeof(cpu_min_freq),\ + 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, \ + CTL_CPU_VARS_SPEED_MIN, \ + 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 } + +#endif /* CONFIG_CPU_FREQ_24_API */ + #endif /* _LINUX_CPUFREQ_H */ diff -ruN linux-2539original/kernel/cpufreq.c linux/kernel/cpufreq.c --- linux-2539original/kernel/cpufreq.c Sun Sep 22 09:00:00 2002 +++ linux/kernel/cpufreq.c Sat Sep 28 09:30:00 2002 @@ -28,6 +28,9 @@ #include #endif +#ifdef CONFIG_CPU_FREQ_24_API +#include +#endif /** @@ -65,6 +68,16 @@ }; +#ifdef CONFIG_CPU_FREQ_24_API +/** + * A few values needed by the 2.4.-compatible API + */ +static unsigned int cpu_max_freq; +static unsigned int cpu_min_freq; +static unsigned int cpu_cur_freq[NR_CPUS]; +#endif + + /********************************************************************* * 2.6. API * @@ -327,6 +340,389 @@ /********************************************************************* + * 2.4. COMPATIBLE API * + *********************************************************************/ + +#ifdef CONFIG_CPU_FREQ_24_API +/* NOTE #1: when you use this API, you may not use any other calls, + * except cpufreq_[un]register_notifier, of course. + */ + +/** + * 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. + */ +int cpufreq_set(unsigned int freq, unsigned int cpu) +{ + struct cpufreq_policy policy; + down(&cpufreq_driver_sem); + if (!cpufreq_driver || !cpu_max_freq) { + up(&cpufreq_driver_sem); + return -EINVAL; + } + + policy.min = freq; + policy.max = freq; + policy.policy = CPUFREQ_POLICY_POWERSAVE; + policy.cpu = cpu; + + up(&cpufreq_driver_sem); + + return cpufreq_set_policy(&policy); +} +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 cpufreq_setmax(unsigned int cpu) +{ + if (!cpu_online(cpu) && (cpu != CPUFREQ_ALL_CPUS)) + return -EINVAL; + return cpufreq_set(cpu_max_freq, cpu); +} +EXPORT_SYMBOL_GPL(cpufreq_setmax); + + +/** + * cpufreq_get - get the current CPU frequency (in kHz) + * @cpu: CPU number - currently without effect. + * + * Get the CPU current (static) CPU frequency + */ +unsigned int cpufreq_get(unsigned int cpu) +{ + if (!cpu_online(cpu)) + return -EINVAL; + return cpu_cur_freq[cpu]; +} +EXPORT_SYMBOL(cpufreq_get); + + +#ifdef CONFIG_SYSCTL + + +/*********************** cpufreq_sysctl interface ********************/ +static int +cpufreq_procctl(ctl_table *ctl, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + char buf[16], *p; + int cpu = (int) ctl->extra1; + int len, left = *lenp; + + if (!left || (filp->f_pos && !write) || !cpu_online(cpu)) { + *lenp = 0; + return 0; + } + + 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; + filp->f_pos += len; + return 0; +} + +static int +cpufreq_sysctl(ctl_table *table, int *name, int nlen, + void *oldval, size_t *oldlenp, + void *newval, size_t newlen, void **context) +{ + int cpu = (int) table->extra1; + + if (!cpu_online(cpu)) + return -EINVAL; + + 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 *)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 *)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, + } +}; + +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() +#define cpufreq_sysctl_exit() +#endif /* CONFIG_SYSCTL */ +#endif /* CONFIG_CPU_FREQ_24_API */ + + + +/********************************************************************* * NOTIFIER LISTS INTERFACE * *********************************************************************/ @@ -484,6 +880,14 @@ cpufreq_driver->policy[policy->cpu].policy = policy->policy; } +#ifdef CONFIG_CPU_FREQ_24_API + if (policy->cpu == CPUFREQ_ALL_CPUS) { + for (i=0;imax; + } else + cpu_cur_freq[policy->cpu] = policy->max; +#endif + cpufreq_driver->setpolicy(policy); up(&cpufreq_driver_sem); @@ -592,6 +996,20 @@ cpufreq_proc_init(); #endif +#ifdef CONFIG_CPU_FREQ_24_API + down(&cpufreq_driver_sem); + cpu_min_freq = driver_data->cpu_min_freq; + cpu_max_freq = driver_data->policy[0].max_cpu_freq; + { + unsigned int i; + for (i=0; icpu_cur_freq[i]; + } + } + up(&cpufreq_driver_sem); + + cpufreq_sysctl_init(); +#endif if (ret) { down(&cpufreq_driver_sem); cpufreq_driver = NULL; @@ -628,6 +1046,10 @@ cpufreq_proc_exit(); #endif +#ifdef CONFIG_CPU_FREQ_24_API + cpufreq_sysctl_exit(); +#endif + return 0; } EXPORT_SYMBOL_GPL(cpufreq_unregister); @@ -666,6 +1088,10 @@ #ifdef CONFIG_CPU_FREQ_26_API cpufreq_set_policy(&policy); +#endif + +#ifdef CONFIG_CPU_FREQ_24_API + cpufreq_set(cpu_cur_freq[i], i); #endif } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/