Pull trivial into test branch
[powerpc.git] / arch / i386 / kernel / cpu / cpufreq / acpi-cpufreq.c
index 8b0c7db..39bc16b 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/sched.h>
 #include <linux/cpufreq.h>
 #include <linux/compiler.h>
-#include <linux/sched.h>       /* current */
 #include <linux/dmi.h>
 
 #include <linux/acpi.h>
@@ -58,10 +57,12 @@ enum {
 };
 
 #define INTEL_MSR_RANGE                (0xffff)
+#define CPUID_6_ECX_APERFMPERF_CAPABILITY      (0x1)
 
 struct acpi_cpufreq_data {
        struct acpi_processor_performance *acpi_data;
        struct cpufreq_frequency_table *freq_table;
+       unsigned int max_freq;
        unsigned int resume;
        unsigned int cpu_feature;
 };
@@ -91,7 +92,7 @@ static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data)
 
        perf = data->acpi_data;
 
-       for (i = 0; i < perf->state_count; i++) {
+       for (i=0; i<perf->state_count; i++) {
                if (value == perf->states[i].status)
                        return data->freq_table[i].frequency;
        }
@@ -106,7 +107,7 @@ static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
        msr &= INTEL_MSR_RANGE;
        perf = data->acpi_data;
 
-       for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+       for (i=0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
                if (msr == perf->states[data->freq_table[i].index].status)
                        return data->freq_table[i].frequency;
        }
@@ -127,25 +128,23 @@ static unsigned extract_freq(u32 val, struct acpi_cpufreq_data *data)
 
 static void wrport(u16 port, u8 bit_width, u32 value)
 {
-       if (bit_width <= 8) {
+       if (bit_width <= 8)
                outb(value, port);
-       } else if (bit_width <= 16) {
+       else if (bit_width <= 16)
                outw(value, port);
-       } else if (bit_width <= 32) {
+       else if (bit_width <= 32)
                outl(value, port);
-       }
 }
 
 static void rdport(u16 port, u8 bit_width, u32 * ret)
 {
        *ret = 0;
-       if (bit_width <= 8) {
+       if (bit_width <= 8)
                *ret = inb(port);
-       } else if (bit_width <= 16) {
+       else if (bit_width <= 16)
                *ret = inw(port);
-       } else if (bit_width <= 32) {
+       else if (bit_width <= 32)
                *ret = inl(port);
-       }
 }
 
 struct msr_addr {
@@ -201,7 +200,7 @@ static void do_drv_write(struct drv_cmd *cmd)
        }
 }
 
-static inline void drv_read(struct drv_cmd *cmd)
+static void drv_read(struct drv_cmd *cmd)
 {
        cpumask_t saved_mask = current->cpus_allowed;
        cmd->val = 0;
@@ -209,7 +208,6 @@ static inline void drv_read(struct drv_cmd *cmd)
        set_cpus_allowed(current, cmd->mask);
        do_drv_read(cmd);
        set_cpus_allowed(current, saved_mask);
-
 }
 
 static void drv_write(struct drv_cmd *cmd)
@@ -258,6 +256,98 @@ static u32 get_cur_val(cpumask_t mask)
        return cmd.val;
 }
 
+/*
+ * Return the measured active (C0) frequency on this CPU since last call
+ * to this function.
+ * Input: cpu number
+ * Return: Average CPU frequency in terms of max frequency (zero on error)
+ *
+ * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance
+ * over a period of time, while CPU is in C0 state.
+ * IA32_MPERF counts at the rate of max advertised frequency
+ * IA32_APERF counts at the rate of actual CPU frequency
+ * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and
+ * no meaning should be associated with absolute values of these MSRs.
+ */
+static unsigned int get_measured_perf(unsigned int cpu)
+{
+       union {
+               struct {
+                       u32 lo;
+                       u32 hi;
+               } split;
+               u64 whole;
+       } aperf_cur, mperf_cur;
+
+       cpumask_t saved_mask;
+       unsigned int perf_percent;
+       unsigned int retval;
+
+       saved_mask = current->cpus_allowed;
+       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+       if (get_cpu() != cpu) {
+               /* We were not able to run on requested processor */
+               put_cpu();
+               return 0;
+       }
+
+       rdmsr(MSR_IA32_APERF, aperf_cur.split.lo, aperf_cur.split.hi);
+       rdmsr(MSR_IA32_MPERF, mperf_cur.split.lo, mperf_cur.split.hi);
+
+       wrmsr(MSR_IA32_APERF, 0,0);
+       wrmsr(MSR_IA32_MPERF, 0,0);
+
+#ifdef __i386__
+       /*
+        * We dont want to do 64 bit divide with 32 bit kernel
+        * Get an approximate value. Return failure in case we cannot get
+        * an approximate value.
+        */
+       if (unlikely(aperf_cur.split.hi || mperf_cur.split.hi)) {
+               int shift_count;
+               u32 h;
+
+               h = max_t(u32, aperf_cur.split.hi, mperf_cur.split.hi);
+               shift_count = fls(h);
+
+               aperf_cur.whole >>= shift_count;
+               mperf_cur.whole >>= shift_count;
+       }
+
+       if (((unsigned long)(-1) / 100) < aperf_cur.split.lo) {
+               int shift_count = 7;
+               aperf_cur.split.lo >>= shift_count;
+               mperf_cur.split.lo >>= shift_count;
+       }
+
+       if (aperf_cur.split.lo && mperf_cur.split.lo)
+               perf_percent = (aperf_cur.split.lo * 100) / mperf_cur.split.lo;
+       else
+               perf_percent = 0;
+
+#else
+       if (unlikely(((unsigned long)(-1) / 100) < aperf_cur.whole)) {
+               int shift_count = 7;
+               aperf_cur.whole >>= shift_count;
+               mperf_cur.whole >>= shift_count;
+       }
+
+       if (aperf_cur.whole && mperf_cur.whole)
+               perf_percent = (aperf_cur.whole * 100) / mperf_cur.whole;
+       else
+               perf_percent = 0;
+
+#endif
+
+       retval = drv_data[cpu]->max_freq * perf_percent / 100;
+
+       put_cpu();
+       set_cpus_allowed(current, saved_mask);
+
+       dprintk("cpu %d: performance percent %d\n", cpu, perf_percent);
+       return retval;
+}
+
 static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
 {
        struct acpi_cpufreq_data *data = drv_data[cpu];
@@ -282,7 +372,7 @@ static unsigned int check_freqs(cpumask_t mask, unsigned int freq,
        unsigned int cur_freq;
        unsigned int i;
 
-       for (i = 0; i < 100; i++) {
+       for (i=0; i<100; i++) {
                cur_freq = extract_freq(get_cur_val(mask), data);
                if (cur_freq == freq)
                        return 1;
@@ -308,7 +398,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
        dprintk("acpi_cpufreq_target %d (%d)\n", target_freq, policy->cpu);
 
        if (unlikely(data == NULL ||
-                    data->acpi_data == NULL || data->freq_table == NULL)) {
+            data->acpi_data == NULL || data->freq_table == NULL)) {
                return -ENODEV;
        }
 
@@ -412,15 +502,15 @@ acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)
                unsigned long freq;
                unsigned long freqn = perf->states[0].core_frequency * 1000;
 
-               for (i = 0; i < (perf->state_count - 1); i++) {
+               for (i=0; i<(perf->state_count-1); i++) {
                        freq = freqn;
-                       freqn = perf->states[i + 1].core_frequency * 1000;
+                       freqn = perf->states[i+1].core_frequency * 1000;
                        if ((2 * cpu_khz) > (freqn + freq)) {
                                perf->state = i;
                                return freq;
                        }
                }
-               perf->state = perf->state_count - 1;
+               perf->state = perf->state_count-1;
                return freqn;
        } else {
                /* assume CPU is at P0... */
@@ -464,6 +554,7 @@ static int acpi_cpufreq_early_init(void)
        return 0;
 }
 
+#ifdef CONFIG_SMP
 /*
  * Some BIOSes do SW_ANY coordination internally, either set it up in hw
  * or do it in BIOS firmware and won't inform about it to OS. If not
@@ -478,6 +569,7 @@ static int sw_any_bug_found(struct dmi_system_id *d)
        return 0;
 }
 
+#ifdef CONFIG_SMP
 static struct dmi_system_id sw_any_bug_dmi_table[] = {
        {
                .callback = sw_any_bug_found,
@@ -490,6 +582,7 @@ static struct dmi_system_id sw_any_bug_dmi_table[] = {
        },
        { }
 };
+#endif
 
 static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
@@ -497,7 +590,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
        unsigned int valid_states = 0;
        unsigned int cpu = policy->cpu;
        struct acpi_cpufreq_data *data;
-       unsigned int l, h;
        unsigned int result = 0;
        struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
        struct acpi_processor_performance *perf;
@@ -514,9 +606,8 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
        data->acpi_data = acpi_perf_data[cpu];
        drv_data[cpu] = data;
 
-       if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
+       if (cpu_has(c, X86_FEATURE_CONSTANT_TSC))
                acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
-       }
 
        result = acpi_processor_register_performance(data->acpi_data, cpu);
        if (result)
@@ -524,8 +615,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 
        perf = data->acpi_data;
        policy->shared_type = perf->shared_type;
+
        /*
-        * Will let policy->cpus know about dependency only when software 
+        * Will let policy->cpus know about dependency only when software
         * coordination is required.
         */
        if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
@@ -573,9 +665,8 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
                goto err_unreg;
        }
 
-       data->freq_table =
-           kmalloc(sizeof(struct cpufreq_frequency_table) *
-                   (perf->state_count + 1), GFP_KERNEL);
+       data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
+                   (perf->state_count+1), GFP_KERNEL);
        if (!data->freq_table) {
                result = -ENOMEM;
                goto err_unreg;
@@ -583,7 +674,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 
        /* detect transition latency */
        policy->cpuinfo.transition_latency = 0;
-       for (i = 0; i < perf->state_count; i++) {
+       for (i=0; i<perf->state_count; i++) {
                if ((perf->states[i].transition_latency * 1000) >
                    policy->cpuinfo.transition_latency)
                        policy->cpuinfo.transition_latency =
@@ -591,10 +682,11 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
        }
        policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 
+       data->max_freq = perf->states[0].core_frequency * 1000;
        /* table init */
-       for (i = 0; i < perf->state_count; i++) {
-               if (i > 0 && perf->states[i].core_frequency ==
-                   perf->states[i - 1].core_frequency)
+       for (i=0; i<perf->state_count; i++) {
+               if (i>0 && perf->states[i].core_frequency ==
+                   perf->states[i-1].core_frequency)
                        continue;
 
                data->freq_table[valid_states].index = i;
@@ -602,12 +694,11 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
                    perf->states[i].core_frequency * 1000;
                valid_states++;
        }
-       data->freq_table[perf->state_count].frequency = CPUFREQ_TABLE_END;
+       data->freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
 
        result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
-       if (result) {
+       if (result)
                goto err_freqfree;
-       }
 
        switch (data->cpu_feature) {
        case ACPI_ADR_SPACE_SYSTEM_IO:
@@ -625,6 +716,14 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
        /* notify BIOS that we exist */
        acpi_processor_notify_smm(THIS_MODULE);
 
+       /* Check for APERF/MPERF support in hardware */
+       if (c->x86_vendor == X86_VENDOR_INTEL && c->cpuid_level >= 6) {
+               unsigned int ecx;
+               ecx = cpuid_ecx(6);
+               if (ecx & CPUID_6_ECX_APERFMPERF_CAPABILITY)
+                       acpi_cpufreq_driver.getavg = get_measured_perf;
+       }
+
        dprintk("CPU%u - ACPI performance management activated.\n", cpu);
        for (i = 0; i < perf->state_count; i++)
                dprintk("     %cP%d: %d MHz, %d mW, %d uS\n",
@@ -643,11 +742,11 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 
        return result;
 
-      err_freqfree:
+err_freqfree:
        kfree(data->freq_table);
-      err_unreg:
+err_unreg:
        acpi_processor_unregister_performance(perf, cpu);
-      err_free:
+err_free:
        kfree(data);
        drv_data[cpu] = NULL;
 
@@ -723,7 +822,8 @@ static void __exit acpi_cpufreq_exit(void)
 
 module_param(acpi_pstate_strict, uint, 0644);
 MODULE_PARM_DESC(acpi_pstate_strict,
-                "value 0 or non-zero. non-zero -> strict ACPI checks are performed during frequency changes.");
+       "value 0 or non-zero. non-zero -> strict ACPI checks are "
+       "performed during frequency changes.");
 
 late_initcall(acpi_cpufreq_init);
 module_exit(acpi_cpufreq_exit);