]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 11 Oct 2008 15:49:34 +0000 (08:49 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 11 Oct 2008 15:49:34 +0000 (08:49 -0700)
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq:
  [CPUFREQ] Fix BUG: using smp_processor_id() in preemptible code
  [CPUFREQ] Don't export governors for default governor
  [CPUFREQ][6/6] cpufreq: Add idle microaccounting in ondemand governor
  [CPUFREQ][5/6] cpufreq: Changes to get_cpu_idle_time_us(), used by ondemand governor
  [CPUFREQ][4/6] cpufreq_ondemand: Parameterize down differential
  [CPUFREQ][3/6] cpufreq: get_cpu_idle_time() changes in ondemand for idle-microaccounting
  [CPUFREQ][2/6] cpufreq: Change load calculation in ondemand for software coordination
  [CPUFREQ][1/6] cpufreq: Add cpu number parameter to __cpufreq_driver_getavg()
  [CPUFREQ] use deferrable delayed work init in conservative governor
  [CPUFREQ] drivers/cpufreq/cpufreq.c: Adjust error handling code involving cpufreq_cpu_put
  [CPUFREQ] add error handling for cpufreq_register_governor() error
  [CPUFREQ] acpi-cpufreq: add error handling for cpufreq_register_driver() error
  [CPUFREQ] Coding style fixes to arch/x86/kernel/cpu/cpufreq/powernow-k6.c
  [CPUFREQ] Coding style fixes to arch/x86/kernel/cpu/cpufreq/elanfreq.c

12 files changed:
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
arch/x86/kernel/cpu/cpufreq/elanfreq.c
arch/x86/kernel/cpu/cpufreq/powernow-k6.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_performance.c
drivers/cpufreq/cpufreq_powersave.c
drivers/cpufreq/cpufreq_userspace.c
include/linux/cpufreq.h
include/linux/tick.h
kernel/time/tick-sched.c

index dd097b835839dd73d4139d807c23e8fca1648344..c24c4a487b7cb05f8ec6ad73998a2e0e01439d32 100644 (file)
@@ -256,7 +256,8 @@ static u32 get_cur_val(const cpumask_t *mask)
  * 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)
+static unsigned int get_measured_perf(struct cpufreq_policy *policy,
+                                     unsigned int cpu)
 {
        union {
                struct {
@@ -326,7 +327,7 @@ static unsigned int get_measured_perf(unsigned int cpu)
 
 #endif
 
-       retval = per_cpu(drv_data, cpu)->max_freq * perf_percent / 100;
+       retval = per_cpu(drv_data, policy->cpu)->max_freq * perf_percent / 100;
 
        put_cpu();
        set_cpus_allowed_ptr(current, &saved_mask);
@@ -785,7 +786,11 @@ static int __init acpi_cpufreq_init(void)
        if (ret)
                return ret;
 
-       return cpufreq_register_driver(&acpi_cpufreq_driver);
+       ret = cpufreq_register_driver(&acpi_cpufreq_driver);
+       if (ret)
+               free_percpu(acpi_perf_data);
+
+       return ret;
 }
 
 static void __exit acpi_cpufreq_exit(void)
@@ -795,8 +800,6 @@ static void __exit acpi_cpufreq_exit(void)
        cpufreq_unregister_driver(&acpi_cpufreq_driver);
 
        free_percpu(acpi_perf_data);
-
-       return;
 }
 
 module_param(acpi_pstate_strict, uint, 0644);
index e4a4bf870e9472e7b3da95ac0d6b9a620ff675b5..fe613c93b3667d73e78ca6747f691232a9233702 100644 (file)
@@ -25,8 +25,8 @@
 #include <linux/cpufreq.h>
 
 #include <asm/msr.h>
-#include <asm/timex.h>
-#include <asm/io.h>
+#include <linux/timex.h>
+#include <linux/io.h>
 
 #define REG_CSCIR 0x22         /* Chip Setup and Control Index Register    */
 #define REG_CSCDR 0x23         /* Chip Setup and Control Data  Register    */
@@ -82,7 +82,7 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu)
        u8 clockspeed_reg;    /* Clock Speed Register */
 
        local_irq_disable();
-       outb_p(0x80,REG_CSCIR);
+       outb_p(0x80, REG_CSCIR);
        clockspeed_reg = inb_p(REG_CSCDR);
        local_irq_enable();
 
@@ -98,10 +98,10 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu)
        }
 
        /* 33 MHz is not 32 MHz... */
-       if ((clockspeed_reg & 0xE0)==0xA0)
+       if ((clockspeed_reg & 0xE0) == 0xA0)
                return 33000;
 
-       return ((1<<((clockspeed_reg & 0xE0) >> 5)) * 1000);
+       return (1<<((clockspeed_reg & 0xE0) >> 5)) * 1000;
 }
 
 
@@ -117,7 +117,7 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu)
  *     There is no return value.
  */
 
-static void elanfreq_set_cpu_state (unsigned int state)
+static void elanfreq_set_cpu_state(unsigned int state)
 {
        struct cpufreq_freqs    freqs;
 
@@ -144,20 +144,20 @@ static void elanfreq_set_cpu_state (unsigned int state)
         */
 
        local_irq_disable();
-       outb_p(0x40,REG_CSCIR);         /* Disable hyperspeed mode */
-       outb_p(0x00,REG_CSCDR);
+       outb_p(0x40, REG_CSCIR);                /* Disable hyperspeed mode */
+       outb_p(0x00, REG_CSCDR);
        local_irq_enable();             /* wait till internal pipelines and */
        udelay(1000);                   /* buffers have cleaned up          */
 
        local_irq_disable();
 
        /* now, set the CPU clock speed register (0x80) */
-       outb_p(0x80,REG_CSCIR);
-       outb_p(elan_multiplier[state].val80h,REG_CSCDR);
+       outb_p(0x80, REG_CSCIR);
+       outb_p(elan_multiplier[state].val80h, REG_CSCDR);
 
        /* now, the hyperspeed bit in PMU Force Mode Register (0x40) */
-       outb_p(0x40,REG_CSCIR);
-       outb_p(elan_multiplier[state].val40h,REG_CSCDR);
+       outb_p(0x40, REG_CSCIR);
+       outb_p(elan_multiplier[state].val40h, REG_CSCDR);
        udelay(10000);
        local_irq_enable();
 
@@ -173,12 +173,12 @@ static void elanfreq_set_cpu_state (unsigned int state)
  *     for the hardware supported by the driver.
  */
 
-static int elanfreq_verify (struct cpufreq_policy *policy)
+static int elanfreq_verify(struct cpufreq_policy *policy)
 {
        return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]);
 }
 
-static int elanfreq_target (struct cpufreq_policy *policy,
+static int elanfreq_target(struct cpufreq_policy *policy,
                            unsigned int target_freq,
                            unsigned int relation)
 {
@@ -205,7 +205,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
 
        /* capability check */
        if ((c->x86_vendor != X86_VENDOR_AMD) ||
-           (c->x86 != 4) || (c->x86_model!=10))
+           (c->x86 != 4) || (c->x86_model != 10))
                return -ENODEV;
 
        /* max freq */
@@ -213,7 +213,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
                max_freq = elanfreq_get_cpu_frequency(0);
 
        /* table init */
-       for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) {
+       for (i = 0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) {
                if (elanfreq_table[i].frequency > max_freq)
                        elanfreq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
        }
@@ -224,7 +224,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
 
        result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table);
        if (result)
-               return (result);
+               return result;
 
        cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu);
        return 0;
@@ -260,7 +260,7 @@ __setup("elanfreq=", elanfreq_setup);
 #endif
 
 
-static struct freq_attrelanfreq_attr[] = {
+static struct freq_attr *elanfreq_attr[] = {
        &cpufreq_freq_attr_scaling_available_freqs,
        NULL,
 };
@@ -284,9 +284,9 @@ static int __init elanfreq_init(void)
 
        /* Test if we have the right hardware */
        if ((c->x86_vendor != X86_VENDOR_AMD) ||
-               (c->x86 != 4) || (c->x86_model!=10)) {
+               (c->x86 != 4) || (c->x86_model != 10)) {
                printk(KERN_INFO "elanfreq: error: no Elan processor found!\n");
-                return -ENODEV;
+               return -ENODEV;
        }
        return cpufreq_register_driver(&elanfreq_driver);
 }
@@ -298,7 +298,7 @@ static void __exit elanfreq_exit(void)
 }
 
 
-module_param (max_freq, int, 0444);
+module_param(max_freq, int, 0444);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Robert Schwebel <r.schwebel@pengutronix.de>, Sven Geggus <sven@geggus.net>");
index eb9b62b0830c8941ee7ea990304596e2a1d82316..b5ced806a316d66b1c4bb1fcc6120f855617a266 100644 (file)
 #include <linux/slab.h>
 
 #include <asm/msr.h>
-#include <asm/timex.h>
-#include <asm/io.h>
+#include <linux/timex.h>
+#include <linux/io.h>
 
-
-#define POWERNOW_IOPORT 0xfff0         /* it doesn't matter where, as long
-                                         as it is unused */
+#define POWERNOW_IOPORT 0xfff0          /* it doesn't matter where, as long
+                                          as it is unused */
 
 static unsigned int                     busfreq;   /* FSB, in 10 kHz */
 static unsigned int                     max_multiplier;
@@ -53,7 +52,7 @@ static int powernow_k6_get_cpu_multiplier(void)
 
        msrval = POWERNOW_IOPORT + 0x1;
        wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
-       invalue=inl(POWERNOW_IOPORT + 0x8);
+       invalue = inl(POWERNOW_IOPORT + 0x8);
        msrval = POWERNOW_IOPORT + 0x0;
        wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
 
@@ -67,9 +66,9 @@ static int powernow_k6_get_cpu_multiplier(void)
  *
  *   Tries to change the PowerNow! multiplier
  */
-static void powernow_k6_set_state (unsigned int best_i)
+static void powernow_k6_set_state(unsigned int best_i)
 {
-       unsigned long           outvalue=0, invalue=0;
+       unsigned long           outvalue = 0, invalue = 0;
        unsigned long           msrval;
        struct cpufreq_freqs    freqs;
 
@@ -90,10 +89,10 @@ static void powernow_k6_set_state (unsigned int best_i)
 
        msrval = POWERNOW_IOPORT + 0x1;
        wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
-       invalue=inl(POWERNOW_IOPORT + 0x8);
+       invalue = inl(POWERNOW_IOPORT + 0x8);
        invalue = invalue & 0xf;
        outvalue = outvalue | invalue;
-       outl(outvalue ,(POWERNOW_IOPORT + 0x8));
+       outl(outvalue , (POWERNOW_IOPORT + 0x8));
        msrval = POWERNOW_IOPORT + 0x0;
        wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
 
@@ -124,7 +123,7 @@ static int powernow_k6_verify(struct cpufreq_policy *policy)
  *
  * sets a new CPUFreq policy
  */
-static int powernow_k6_target (struct cpufreq_policy *policy,
+static int powernow_k6_target(struct cpufreq_policy *policy,
                               unsigned int target_freq,
                               unsigned int relation)
 {
@@ -152,7 +151,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
        busfreq = cpu_khz / max_multiplier;
 
        /* table init */
-       for (i=0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
+       for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
                if (clock_ratio[i].index > max_multiplier)
                        clock_ratio[i].frequency = CPUFREQ_ENTRY_INVALID;
                else
@@ -165,7 +164,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
 
        result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio);
        if (result)
-               return (result);
+               return result;
 
        cpufreq_frequency_table_get_attr(clock_ratio, policy->cpu);
 
@@ -176,8 +175,8 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
 static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
 {
        unsigned int i;
-       for (i=0; i<8; i++) {
-               if (i==max_multiplier)
+       for (i = 0; i < 8; i++) {
+               if (i == max_multiplier)
                        powernow_k6_set_state(i);
        }
        cpufreq_frequency_table_put_attr(policy->cpu);
@@ -189,7 +188,7 @@ static unsigned int powernow_k6_get(unsigned int cpu)
        return busfreq * powernow_k6_get_cpu_multiplier();
 }
 
-static struct freq_attrpowernow_k6_attr[] = {
+static struct freq_attr *powernow_k6_attr[] = {
        &cpufreq_freq_attr_scaling_available_freqs,
        NULL,
 };
@@ -227,7 +226,7 @@ static int __init powernow_k6_init(void)
        }
 
        if (cpufreq_register_driver(&powernow_k6_driver)) {
-               release_region (POWERNOW_IOPORT, 16);
+               release_region(POWERNOW_IOPORT, 16);
                return -EINVAL;
        }
 
@@ -243,13 +242,13 @@ static int __init powernow_k6_init(void)
 static void __exit powernow_k6_exit(void)
 {
        cpufreq_unregister_driver(&powernow_k6_driver);
-       release_region (POWERNOW_IOPORT, 16);
+       release_region(POWERNOW_IOPORT, 16);
 }
 
 
-MODULE_AUTHOR ("Arjan van de Ven <arjanv@redhat.com>, Dave Jones <davej@codemonkey.org.uk>, Dominik Brodowski <linux@brodo.de>");
-MODULE_DESCRIPTION ("PowerNow! driver for AMD K6-2+ / K6-3+ processors.");
-MODULE_LICENSE ("GPL");
+MODULE_AUTHOR("Arjan van de Ven <arjanv@redhat.com>, Dave Jones <davej@codemonkey.org.uk>, Dominik Brodowski <linux@brodo.de>");
+MODULE_DESCRIPTION("PowerNow! driver for AMD K6-2+ / K6-3+ processors.");
+MODULE_LICENSE("GPL");
 
 module_init(powernow_k6_init);
 module_exit(powernow_k6_exit);
index 8a67f16987db16582e87a49514cf3a99158d542e..31d6f535a79de51d322d8d76af3eccfd2bf11140 100644 (file)
@@ -1467,25 +1467,27 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
                          unsigned int target_freq,
                          unsigned int relation)
 {
-       int ret;
+       int ret = -EINVAL;
 
        policy = cpufreq_cpu_get(policy->cpu);
        if (!policy)
-               return -EINVAL;
+               goto no_policy;
 
        if (unlikely(lock_policy_rwsem_write(policy->cpu)))
-               return -EINVAL;
+               goto fail;
 
        ret = __cpufreq_driver_target(policy, target_freq, relation);
 
        unlock_policy_rwsem_write(policy->cpu);
 
+fail:
        cpufreq_cpu_put(policy);
+no_policy:
        return ret;
 }
 EXPORT_SYMBOL_GPL(cpufreq_driver_target);
 
-int __cpufreq_driver_getavg(struct cpufreq_policy *policy)
+int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu)
 {
        int ret = 0;
 
@@ -1493,8 +1495,8 @@ int __cpufreq_driver_getavg(struct cpufreq_policy *policy)
        if (!policy)
                return -EINVAL;
 
-       if (cpu_online(policy->cpu) && cpufreq_driver->getavg)
-               ret = cpufreq_driver->getavg(policy->cpu);
+       if (cpu_online(cpu) && cpufreq_driver->getavg)
+               ret = cpufreq_driver->getavg(policycpu);
 
        cpufreq_cpu_put(policy);
        return ret;
@@ -1717,13 +1719,17 @@ int cpufreq_update_policy(unsigned int cpu)
 {
        struct cpufreq_policy *data = cpufreq_cpu_get(cpu);
        struct cpufreq_policy policy;
-       int ret = 0;
+       int ret;
 
-       if (!data)
-               return -ENODEV;
+       if (!data) {
+               ret = -ENODEV;
+               goto no_policy;
+       }
 
-       if (unlikely(lock_policy_rwsem_write(cpu)))
-               return -EINVAL;
+       if (unlikely(lock_policy_rwsem_write(cpu))) {
+               ret = -EINVAL;
+               goto fail;
+       }
 
        dprintk("updating policy for CPU %u\n", cpu);
        memcpy(&policy, data, sizeof(struct cpufreq_policy));
@@ -1750,7 +1756,9 @@ int cpufreq_update_policy(unsigned int cpu)
 
        unlock_policy_rwsem_write(cpu);
 
+fail:
        cpufreq_cpu_put(data);
+no_policy:
        return ret;
 }
 EXPORT_SYMBOL(cpufreq_update_policy);
index ac0bbf2d234f3c72ecb5e6d781bc25afeef1afae..e2657837d954a459a731639811fcf3e4b7d91399 100644 (file)
@@ -460,6 +460,7 @@ static void do_dbs_timer(struct work_struct *work)
 
 static inline void dbs_timer_init(void)
 {
+       init_timer_deferrable(&dbs_work.timer);
        schedule_delayed_work(&dbs_work,
                        usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
        return;
@@ -575,13 +576,15 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
        return 0;
 }
 
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
+static
+#endif
 struct cpufreq_governor cpufreq_gov_conservative = {
        .name                   = "conservative",
        .governor               = cpufreq_governor_dbs,
        .max_transition_latency = TRANSITION_LATENCY_LIMIT,
        .owner                  = THIS_MODULE,
 };
-EXPORT_SYMBOL(cpufreq_gov_conservative);
 
 static int __init cpufreq_gov_dbs_init(void)
 {
index 33855cb3cf16f1ecd30528f35343c2c029959b1e..2ab3c12b88afbd733fe5fd521a8dcc98540f8f3b 100644 (file)
 #include <linux/jiffies.h>
 #include <linux/kernel_stat.h>
 #include <linux/mutex.h>
+#include <linux/hrtimer.h>
+#include <linux/tick.h>
+#include <linux/ktime.h>
 
 /*
  * dbs is used in this file as a shortform for demandbased switching
  * It helps to keep variable names smaller, simpler
  */
 
+#define DEF_FREQUENCY_DOWN_DIFFERENTIAL                (10)
 #define DEF_FREQUENCY_UP_THRESHOLD             (80)
+#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL      (3)
+#define MICRO_FREQUENCY_UP_THRESHOLD           (95)
 #define MIN_FREQUENCY_UP_THRESHOLD             (11)
 #define MAX_FREQUENCY_UP_THRESHOLD             (100)
 
@@ -57,6 +63,7 @@ enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
 struct cpu_dbs_info_s {
        cputime64_t prev_cpu_idle;
        cputime64_t prev_cpu_wall;
+       cputime64_t prev_cpu_nice;
        struct cpufreq_policy *cur_policy;
        struct delayed_work work;
        struct cpufreq_frequency_table *freq_table;
@@ -86,21 +93,24 @@ static struct workqueue_struct      *kondemand_wq;
 static struct dbs_tuners {
        unsigned int sampling_rate;
        unsigned int up_threshold;
+       unsigned int down_differential;
        unsigned int ignore_nice;
        unsigned int powersave_bias;
 } dbs_tuners_ins = {
        .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
+       .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL,
        .ignore_nice = 0,
        .powersave_bias = 0,
 };
 
-static inline cputime64_t get_cpu_idle_time(unsigned int cpu)
+static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu,
+                                                       cputime64_t *wall)
 {
        cputime64_t idle_time;
-       cputime64_t cur_jiffies;
+       cputime64_t cur_wall_time;
        cputime64_t busy_time;
 
-       cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
+       cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
        busy_time = cputime64_add(kstat_cpu(cpu).cpustat.user,
                        kstat_cpu(cpu).cpustat.system);
 
@@ -113,7 +123,37 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu)
                                kstat_cpu(cpu).cpustat.nice);
        }
 
-       idle_time = cputime64_sub(cur_jiffies, busy_time);
+       idle_time = cputime64_sub(cur_wall_time, busy_time);
+       if (wall)
+               *wall = cur_wall_time;
+
+       return idle_time;
+}
+
+static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
+{
+       u64 idle_time = get_cpu_idle_time_us(cpu, wall);
+
+       if (idle_time == -1ULL)
+               return get_cpu_idle_time_jiffy(cpu, wall);
+
+       if (dbs_tuners_ins.ignore_nice) {
+               cputime64_t cur_nice;
+               unsigned long cur_nice_jiffies;
+               struct cpu_dbs_info_s *dbs_info;
+
+               dbs_info = &per_cpu(cpu_dbs_info, cpu);
+               cur_nice = cputime64_sub(kstat_cpu(cpu).cpustat.nice,
+                                        dbs_info->prev_cpu_nice);
+               /*
+                * Assumption: nice time between sampling periods will be
+                * less than 2^32 jiffies for 32 bit sys
+                */
+               cur_nice_jiffies = (unsigned long)
+                                       cputime64_to_jiffies64(cur_nice);
+               dbs_info->prev_cpu_nice = kstat_cpu(cpu).cpustat.nice;
+               return idle_time + jiffies_to_usecs(cur_nice_jiffies);
+       }
        return idle_time;
 }
 
@@ -277,8 +317,8 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
        for_each_online_cpu(j) {
                struct cpu_dbs_info_s *dbs_info;
                dbs_info = &per_cpu(cpu_dbs_info, j);
-               dbs_info->prev_cpu_idle = get_cpu_idle_time(j);
-               dbs_info->prev_cpu_wall = get_jiffies_64();
+               dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
+                                               &dbs_info->prev_cpu_wall);
        }
        mutex_unlock(&dbs_mutex);
 
@@ -334,9 +374,7 @@ static struct attribute_group dbs_attr_group = {
 
 static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
 {
-       unsigned int idle_ticks, total_ticks;
-       unsigned int load = 0;
-       cputime64_t cur_jiffies;
+       unsigned int max_load_freq;
 
        struct cpufreq_policy *policy;
        unsigned int j;
@@ -346,13 +384,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
 
        this_dbs_info->freq_lo = 0;
        policy = this_dbs_info->cur_policy;
-       cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
-       total_ticks = (unsigned int) cputime64_sub(cur_jiffies,
-                       this_dbs_info->prev_cpu_wall);
-       this_dbs_info->prev_cpu_wall = get_jiffies_64();
 
-       if (!total_ticks)
-               return;
        /*
         * Every sampling_rate, we check, if current idle time is less
         * than 20% (default), then we try to increase frequency
@@ -365,27 +397,44 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
         * 5% (default) of current frequency
         */
 
-       /* Get Idle Time */
-       idle_ticks = UINT_MAX;
+       /* Get Absolute Load - in terms of freq */
+       max_load_freq = 0;
+
        for_each_cpu_mask_nr(j, policy->cpus) {
-               cputime64_t total_idle_ticks;
-               unsigned int tmp_idle_ticks;
                struct cpu_dbs_info_s *j_dbs_info;
+               cputime64_t cur_wall_time, cur_idle_time;
+               unsigned int idle_time, wall_time;
+               unsigned int load, load_freq;
+               int freq_avg;
 
                j_dbs_info = &per_cpu(cpu_dbs_info, j);
-               total_idle_ticks = get_cpu_idle_time(j);
-               tmp_idle_ticks = (unsigned int) cputime64_sub(total_idle_ticks,
+
+               cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
+
+               wall_time = (unsigned int) cputime64_sub(cur_wall_time,
+                               j_dbs_info->prev_cpu_wall);
+               j_dbs_info->prev_cpu_wall = cur_wall_time;
+
+               idle_time = (unsigned int) cputime64_sub(cur_idle_time,
                                j_dbs_info->prev_cpu_idle);
-               j_dbs_info->prev_cpu_idle = total_idle_ticks;
+               j_dbs_info->prev_cpu_idle = cur_idle_time;
+
+               if (unlikely(!wall_time || wall_time < idle_time))
+                       continue;
+
+               load = 100 * (wall_time - idle_time) / wall_time;
+
+               freq_avg = __cpufreq_driver_getavg(policy, j);
+               if (freq_avg <= 0)
+                       freq_avg = policy->cur;
 
-               if (tmp_idle_ticks < idle_ticks)
-                       idle_ticks = tmp_idle_ticks;
+               load_freq = load * freq_avg;
+               if (load_freq > max_load_freq)
+                       max_load_freq = load_freq;
        }
-       if (likely(total_ticks > idle_ticks))
-               load = (100 * (total_ticks - idle_ticks)) / total_ticks;
 
        /* Check for frequency increase */
-       if (load > dbs_tuners_ins.up_threshold) {
+       if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
                /* if we are already at full speed then break out early */
                if (!dbs_tuners_ins.powersave_bias) {
                        if (policy->cur == policy->max)
@@ -412,15 +461,13 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
         * can support the current CPU usage without triggering the up
         * policy. To be safe, we focus 10 points under the threshold.
         */
-       if (load < (dbs_tuners_ins.up_threshold - 10)) {
-               unsigned int freq_next, freq_cur;
-
-               freq_cur = __cpufreq_driver_getavg(policy);
-               if (!freq_cur)
-                       freq_cur = policy->cur;
-
-               freq_next = (freq_cur * load) /
-                       (dbs_tuners_ins.up_threshold - 10);
+       if (max_load_freq <
+           (dbs_tuners_ins.up_threshold - dbs_tuners_ins.down_differential) *
+            policy->cur) {
+               unsigned int freq_next;
+               freq_next = max_load_freq /
+                               (dbs_tuners_ins.up_threshold -
+                                dbs_tuners_ins.down_differential);
 
                if (!dbs_tuners_ins.powersave_bias) {
                        __cpufreq_driver_target(policy, freq_next,
@@ -526,8 +573,8 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                        j_dbs_info = &per_cpu(cpu_dbs_info, j);
                        j_dbs_info->cur_policy = policy;
 
-                       j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j);
-                       j_dbs_info->prev_cpu_wall = get_jiffies_64();
+                       j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
+                                               &j_dbs_info->prev_cpu_wall);
                }
                this_dbs_info->cpu = cpu;
                /*
@@ -579,22 +626,42 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
        return 0;
 }
 
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
+static
+#endif
 struct cpufreq_governor cpufreq_gov_ondemand = {
        .name                   = "ondemand",
        .governor               = cpufreq_governor_dbs,
        .max_transition_latency = TRANSITION_LATENCY_LIMIT,
        .owner                  = THIS_MODULE,
 };
-EXPORT_SYMBOL(cpufreq_gov_ondemand);
 
 static int __init cpufreq_gov_dbs_init(void)
 {
+       int err;
+       cputime64_t wall;
+       u64 idle_time;
+       int cpu = get_cpu();
+
+       idle_time = get_cpu_idle_time_us(cpu, &wall);
+       put_cpu();
+       if (idle_time != -1ULL) {
+               /* Idle micro accounting is supported. Use finer thresholds */
+               dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
+               dbs_tuners_ins.down_differential =
+                                       MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
+       }
+
        kondemand_wq = create_workqueue("kondemand");
        if (!kondemand_wq) {
                printk(KERN_ERR "Creation of kondemand failed\n");
                return -EFAULT;
        }
-       return cpufreq_register_governor(&cpufreq_gov_ondemand);
+       err = cpufreq_register_governor(&cpufreq_gov_ondemand);
+       if (err)
+               destroy_workqueue(kondemand_wq);
+
+       return err;
 }
 
 static void __exit cpufreq_gov_dbs_exit(void)
index e8e1451ef1c1036e30e8b6902ec312457b7f7b5c..7e2e515087f89aba2498508460d1125f2f9f9f68 100644 (file)
@@ -36,12 +36,14 @@ static int cpufreq_governor_performance(struct cpufreq_policy *policy,
        return 0;
 }
 
+#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE_MODULE
+static
+#endif
 struct cpufreq_governor cpufreq_gov_performance = {
        .name           = "performance",
        .governor       = cpufreq_governor_performance,
        .owner          = THIS_MODULE,
 };
-EXPORT_SYMBOL(cpufreq_gov_performance);
 
 
 static int __init cpufreq_gov_performance_init(void)
index 88d2f44fba480f7a66d00ed2fdeb571120926659..e6db5faf3eb112f118cf8ce920168b3635602b78 100644 (file)
@@ -35,12 +35,14 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
        return 0;
 }
 
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE
+static
+#endif
 struct cpufreq_governor cpufreq_gov_powersave = {
        .name           = "powersave",
        .governor       = cpufreq_governor_powersave,
        .owner          = THIS_MODULE,
 };
-EXPORT_SYMBOL(cpufreq_gov_powersave);
 
 static int __init cpufreq_gov_powersave_init(void)
 {
index 32244aa7cc0c1d5b8511d3486a1c8de9b1a59f7c..1442bbada05303bae02adcd3026f57aed4d55a4d 100644 (file)
@@ -187,6 +187,9 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
 }
 
 
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
+static
+#endif
 struct cpufreq_governor cpufreq_gov_userspace = {
        .name           = "userspace",
        .governor       = cpufreq_governor_userspace,
@@ -194,7 +197,6 @@ struct cpufreq_governor cpufreq_gov_userspace = {
        .show_setspeed  = show_speed,
        .owner          = THIS_MODULE,
 };
-EXPORT_SYMBOL(cpufreq_gov_userspace);
 
 static int __init cpufreq_gov_userspace_init(void)
 {
index 6fd5668aa572079f4cd81dc36326aa93a4faddde..1ee608fd7b77c35bee3639c449f6f6483de2bc7c 100644 (file)
@@ -187,7 +187,8 @@ extern int __cpufreq_driver_target(struct cpufreq_policy *policy,
                                   unsigned int relation);
 
 
-extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy);
+extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy,
+                                  unsigned int cpu);
 
 int cpufreq_register_governor(struct cpufreq_governor *governor);
 void cpufreq_unregister_governor(struct cpufreq_governor *governor);
@@ -226,7 +227,9 @@ struct cpufreq_driver {
        unsigned int    (*get)  (unsigned int cpu);
 
        /* optional */
-       unsigned int (*getavg)  (unsigned int cpu);
+       unsigned int (*getavg)  (struct cpufreq_policy *policy,
+                                unsigned int cpu);
+
        int     (*exit)         (struct cpufreq_policy *policy);
        int     (*suspend)      (struct cpufreq_policy *policy, pm_message_t pmsg);
        int     (*resume)       (struct cpufreq_policy *policy);
index 8cf8cfe2cc9712a176d7d4904107f4d30e74293f..98921a3e1aa8db33b7e743e6711abb671485ea12 100644 (file)
@@ -126,7 +126,7 @@ static inline ktime_t tick_nohz_get_sleep_length(void)
        return len;
 }
 static inline void tick_nohz_stop_idle(int cpu) { }
-static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return 0; }
+static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; }
 # endif /* !NO_HZ */
 
 #endif
index cb02324bdb88b1c477f055af028bd4eace476d4d..a4d2193981675aa7b5e2048bf229d5dbdbeccdcd 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/profile.h>
 #include <linux/sched.h>
 #include <linux/tick.h>
+#include <linux/module.h>
 
 #include <asm/irq_regs.h>
 
@@ -190,9 +191,17 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
 {
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
 
-       *last_update_time = ktime_to_us(ts->idle_lastupdate);
+       if (!tick_nohz_enabled)
+               return -1;
+
+       if (ts->idle_active)
+               *last_update_time = ktime_to_us(ts->idle_lastupdate);
+       else
+               *last_update_time = ktime_to_us(ktime_get());
+
        return ktime_to_us(ts->idle_sleeptime);
 }
+EXPORT_SYMBOL_GPL(get_cpu_idle_time_us);
 
 /**
  * tick_nohz_stop_sched_tick - stop the idle tick from the idle task