[CPUFREQ] CPU frequency display in /proc/cpuinfo
authorVenkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Fri, 2 Dec 2005 18:43:20 +0000 (10:43 -0800)
committerDave Jones <davej@redhat.com>
Wed, 7 Dec 2005 03:35:11 +0000 (19:35 -0800)
What is the value shown in "cpu MHz" of /proc/cpuinfo when CPUs are capable of
changing frequency?

Today the answer is: It depends.
On i386:
SMP kernel - It is always the boot frequency
UP kernel - Scales with the frequency change and shows that was last set.

On x86_64:
There is one single variable cpu_khz that gets written by all the CPUs. So,
the frequency set by last CPU will be seen on /proc/cpuinfo of all the
CPUs in the system. What you see also depends on whether you have constant_tsc
capable CPU or not.

On ia64:
It is always boot time frequency of a particular CPU that gets displayed.

The patch below changes this to:
Show the last known frequency of the particular CPU, when cpufreq is present. If
cpu doesnot support changing of frequency through cpufreq, then boot frequency
will be shown. The patch affects i386, x86_64 and ia64 architectures.

Signed-off-by: Venkatesh Pallipadi<venkatesh.pallipadi@intel.com>
Signed-off-by: Dave Jones <davej@redhat.com>
arch/i386/kernel/cpu/proc.c
arch/ia64/kernel/setup.c
arch/x86_64/kernel/setup.c
drivers/cpufreq/cpufreq.c
include/linux/cpufreq.h

index e7921315ae9d8fe5df562cc745f908b6081ed1ab..6d91b274589c7fff2bef8e0d35aaa90c41de71a6 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/string.h>
 #include <asm/semaphore.h>
 #include <linux/seq_file.h>
+#include <linux/cpufreq.h>
 
 /*
  *     Get CPU information for use by the procfs.
@@ -86,8 +87,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                seq_printf(m, "stepping\t: unknown\n");
 
        if ( cpu_has(c, X86_FEATURE_TSC) ) {
+               unsigned int freq = cpufreq_quick_get(n);
+               if (!freq)
+                       freq = cpu_khz;
                seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
-                       cpu_khz / 1000, (cpu_khz % 1000));
+                       freq / 1000, (freq % 1000));
        }
 
        /* Cache size */
index 5add0bcf87a7a338974d39fbff41fe68ce3d6956..088e5dded8dc1c2be9706ffd5819499b433f8513 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/initrd.h>
 #include <linux/platform.h>
 #include <linux/pm.h>
+#include <linux/cpufreq.h>
 
 #include <asm/ia32.h>
 #include <asm/machvec.h>
@@ -517,6 +518,7 @@ show_cpuinfo (struct seq_file *m, void *v)
        char family[32], features[128], *cp, sep;
        struct cpuinfo_ia64 *c = v;
        unsigned long mask;
+       unsigned int proc_freq;
        int i;
 
        mask = c->features;
@@ -549,6 +551,10 @@ show_cpuinfo (struct seq_file *m, void *v)
                sprintf(cp, " 0x%lx", mask);
        }
 
+       proc_freq = cpufreq_quick_get(cpunum);
+       if (!proc_freq)
+               proc_freq = c->proc_freq / 1000;
+
        seq_printf(m,
                   "processor  : %d\n"
                   "vendor     : %s\n"
@@ -565,7 +571,7 @@ show_cpuinfo (struct seq_file *m, void *v)
                   "BogoMIPS   : %lu.%02lu\n",
                   cpunum, c->vendor, family, c->model, c->revision, c->archrev,
                   features, c->ppn, c->number,
-                  c->proc_freq / 1000000, c->proc_freq % 1000000,
+                  proc_freq / 1000, proc_freq % 1000,
                   c->itc_freq / 1000000, c->itc_freq % 1000000,
                   lpj*HZ/500000, (lpj*HZ/5000) % 100);
 #ifdef CONFIG_SMP
index 750e01dcbdf49f364940c87f5ab6b4bc158d460a..64c4534b930c74bc118cf1530a812401456f3d4e 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/edd.h>
 #include <linux/mmzone.h>
 #include <linux/kexec.h>
+#include <linux/cpufreq.h>
 
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
@@ -1256,8 +1257,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                seq_printf(m, "stepping\t: unknown\n");
        
        if (cpu_has(c,X86_FEATURE_TSC)) {
+               unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data));
+               if (!freq)
+                       freq = cpu_khz;
                seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
-                            cpu_khz / 1000, (cpu_khz % 1000));
+                            freq / 1000, (freq % 1000));
        }
 
        /* Cache size */
index 815902c2c856bd08df4da65daaf996f78f07e419..a9163d02983af68f069887a520330e84470cc58b 100644 (file)
@@ -822,6 +822,30 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne
 }
 
 
+/** 
+ * cpufreq_quick_get - get the CPU frequency (in kHz) frpm policy->cur
+ * @cpu: CPU number
+ *
+ * This is the last known freq, without actually getting it from the driver.
+ * Return value will be same as what is shown in scaling_cur_freq in sysfs.
+ */
+unsigned int cpufreq_quick_get(unsigned int cpu)
+{
+       struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+       unsigned int ret = 0;
+
+       if (policy) {
+               down(&policy->lock);
+               ret = policy->cur;
+               up(&policy->lock);
+               cpufreq_cpu_put(policy);
+       }
+
+       return (ret);
+}
+EXPORT_SYMBOL(cpufreq_quick_get);
+
+
 /** 
  * cpufreq_get - get the current CPU frequency (in kHz)
  * @cpu: CPU number
index d068176b7ad7f4d7242e2417f87e3f67043b1d23..c31650df92412de9c6514e81bc5955e8f8a02dcb 100644 (file)
@@ -256,6 +256,16 @@ int cpufreq_update_policy(unsigned int cpu);
 /* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */
 unsigned int cpufreq_get(unsigned int cpu);
 
+/* query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it */
+#ifdef CONFIG_CPU_FREQ
+unsigned int cpufreq_quick_get(unsigned int cpu);
+#else
+static inline unsigned int cpufreq_quick_get(unsigned int cpu)
+{
+       return 0;
+}
+#endif
+
 
 /*********************************************************************
  *                       CPUFREQ DEFAULT GOVERNOR                    *