(5/5) CPUfreq /proc/sys/cpu/ add-on patch

(5/5) CPUfreq /proc/sys/cpu/ add-on patch

Post by Dominik Brodowsk » Sun, 29 Sep 2002 11:50:04



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 <linux/proc_fs.h>
 #endif

+#ifdef CONFIG_CPU_FREQ_24_API
+#include <linux/sysctl.h>
+#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;i<NR_CPUS;i++)
+                       cpu_cur_freq[i] = policy->max;
+       } 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; i<NR_CPUS; i++) {
+                       cpu_cur_freq[i] = driver_data->cpu_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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/