Merge branch 'merge' of master.kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc
[powerpc.git] / drivers / cpufreq / cpufreq_ondemand.c
index bf8aa45..f697449 100644 (file)
 static unsigned int def_sampling_rate;
 #define MIN_SAMPLING_RATE_RATIO                        (2)
 /* for correct statistics, we need at least 10 ticks between each measure */
-#define MIN_STAT_SAMPLING_RATE                 (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
-#define MIN_SAMPLING_RATE                      (def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
+#define MIN_STAT_SAMPLING_RATE                         \
+                       (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
+#define MIN_SAMPLING_RATE                      \
+                       (def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
 #define MAX_SAMPLING_RATE                      (500 * def_sampling_rate)
 #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER   (1000)
 #define TRANSITION_LATENCY_LIMIT               (10 * 1000)
 
-static void do_dbs_timer(void *data);
+static void do_dbs_timer(struct work_struct *work);
+
+/* Sampling types */
+enum dbs_sample {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
 
 struct cpu_dbs_info_s {
        cputime64_t prev_cpu_idle;
        cputime64_t prev_cpu_wall;
        struct cpufreq_policy *cur_policy;
-       struct work_struct work;
+       struct delayed_work work;
+       enum dbs_sample sample_type;
        unsigned int enable;
        struct cpufreq_frequency_table *freq_table;
        unsigned int freq_lo;
@@ -202,7 +208,8 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
        ret = sscanf(buf, "%u", &input);
 
        mutex_lock(&dbs_mutex);
-       if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) {
+       if (ret != 1 || input > MAX_SAMPLING_RATE
+                    || input < MIN_SAMPLING_RATE) {
                mutex_unlock(&dbs_mutex);
                return -EINVAL;
        }
@@ -393,8 +400,15 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
         * policy. To be safe, we focus 10 points under the threshold.
         */
        if (load < (dbs_tuners_ins.up_threshold - 10)) {
-               unsigned int freq_next = (policy->cur * load) /
+               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 (!dbs_tuners_ins.powersave_bias) {
                        __cpufreq_driver_target(policy, freq_next,
                                        CPUFREQ_RELATION_L);
@@ -407,30 +421,31 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
        }
 }
 
-/* Sampling types */
-enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
-
-static void do_dbs_timer(void *data)
+static void do_dbs_timer(struct work_struct *work)
 {
        unsigned int cpu = smp_processor_id();
        struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
+       enum dbs_sample sample_type = dbs_info->sample_type;
        /* We want all CPUs to do sampling nearly on same jiffy */
        int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+
+       /* Permit rescheduling of this work item */
+       work_release(work);
+
        delay -= jiffies % delay;
 
        if (!dbs_info->enable)
                return;
        /* Common NORMAL_SAMPLE setup */
-       INIT_WORK(&dbs_info->work, do_dbs_timer, (void *)DBS_NORMAL_SAMPLE);
+       dbs_info->sample_type = DBS_NORMAL_SAMPLE;
        if (!dbs_tuners_ins.powersave_bias ||
-           (unsigned long) data == DBS_NORMAL_SAMPLE) {
+           sample_type == DBS_NORMAL_SAMPLE) {
                lock_cpu_hotplug();
                dbs_check_cpu(dbs_info);
                unlock_cpu_hotplug();
                if (dbs_info->freq_lo) {
                        /* Setup timer for SUB_SAMPLE */
-                       INIT_WORK(&dbs_info->work, do_dbs_timer,
-                                       (void *)DBS_SUB_SAMPLE);
+                       dbs_info->sample_type = DBS_SUB_SAMPLE;
                        delay = dbs_info->freq_hi_jiffies;
                }
        } else {
@@ -449,7 +464,8 @@ static inline void dbs_timer_init(unsigned int cpu)
        delay -= jiffies % delay;
 
        ondemand_powersave_bias_init();
-       INIT_WORK(&dbs_info->work, do_dbs_timer, NULL);
+       INIT_DELAYED_WORK_NAR(&dbs_info->work, do_dbs_timer);
+       dbs_info->sample_type = DBS_NORMAL_SAMPLE;
        queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
 }
 
@@ -466,6 +482,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
        unsigned int cpu = policy->cpu;
        struct cpu_dbs_info_s *this_dbs_info;
        unsigned int j;
+       int rc;
 
        this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
 
@@ -488,12 +505,23 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                if (dbs_enable == 1) {
                        kondemand_wq = create_workqueue("kondemand");
                        if (!kondemand_wq) {
-                               printk(KERN_ERR "Creation of kondemand failed\n");
+                               printk(KERN_ERR
+                                        "Creation of kondemand failed\n");
                                dbs_enable--;
                                mutex_unlock(&dbs_mutex);
                                return -ENOSPC;
                        }
                }
+
+               rc = sysfs_create_group(&policy->kobj, &dbs_attr_group);
+               if (rc) {
+                       if (dbs_enable == 1)
+                               destroy_workqueue(kondemand_wq);
+                       dbs_enable--;
+                       mutex_unlock(&dbs_mutex);
+                       return rc;
+               }
+
                for_each_cpu_mask(j, policy->cpus) {
                        struct cpu_dbs_info_s *j_dbs_info;
                        j_dbs_info = &per_cpu(cpu_dbs_info, j);
@@ -503,7 +531,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                        j_dbs_info->prev_cpu_wall = get_jiffies_64();
                }
                this_dbs_info->enable = 1;
-               sysfs_create_group(&policy->kobj, &dbs_attr_group);
                /*
                 * Start the timerschedule work, when this governor
                 * is used for first time