]> Pileus Git - ~andy/linux/blobdiff - drivers/cpufreq/cpufreq_governor.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux...
[~andy/linux] / drivers / cpufreq / cpufreq_governor.c
index 29d6a59b1a15bfac33fd526db452fb70ed764818..5a76086ff09becd77fff867d05b6f2782da50f0f 100644 (file)
@@ -177,6 +177,25 @@ static inline void dbs_timer_exit(struct dbs_data *dbs_data, int cpu)
        cancel_delayed_work_sync(&cdbs->work);
 }
 
+/* Will return if we need to evaluate cpu load again or not */
+bool need_load_eval(struct cpu_dbs_common_info *cdbs,
+               unsigned int sampling_rate)
+{
+       if (policy_is_shared(cdbs->cur_policy)) {
+               ktime_t time_now = ktime_get();
+               s64 delta_us = ktime_us_delta(time_now, cdbs->time_stamp);
+
+               /* Do nothing if we recently have sampled */
+               if (delta_us < (s64)(sampling_rate / 2))
+                       return false;
+               else
+                       cdbs->time_stamp = time_now;
+       }
+
+       return true;
+}
+EXPORT_SYMBOL_GPL(need_load_eval);
+
 int cpufreq_governor_dbs(struct dbs_data *dbs_data,
                struct cpufreq_policy *policy, unsigned int event)
 {
@@ -206,7 +225,7 @@ int cpufreq_governor_dbs(struct dbs_data *dbs_data,
 
        switch (event) {
        case CPUFREQ_GOV_START:
-               if ((!cpu_online(cpu)) || (!policy->cur))
+               if (!policy->cur)
                        return -EINVAL;
 
                mutex_lock(&dbs_data->mutex);
@@ -228,18 +247,15 @@ int cpufreq_governor_dbs(struct dbs_data *dbs_data,
                                             dbs_data->gov_dbs_timer);
                }
 
-               rc = sysfs_create_group(cpufreq_global_kobject,
-                               dbs_data->attr_group);
-               if (rc) {
-                       mutex_unlock(&dbs_data->mutex);
-                       return rc;
+               if (!policy->governor->initialized) {
+                       rc = sysfs_create_group(cpufreq_global_kobject,
+                                       dbs_data->attr_group);
+                       if (rc) {
+                               mutex_unlock(&dbs_data->mutex);
+                               return rc;
+                       }
                }
 
-               /* policy latency is in nS. Convert it to uS first */
-               latency = policy->cpuinfo.transition_latency / 1000;
-               if (latency == 0)
-                       latency = 1;
-
                /*
                 * conservative does not implement micro like ondemand
                 * governor, thus we are bound to jiffes/HZ
@@ -248,23 +264,38 @@ int cpufreq_governor_dbs(struct dbs_data *dbs_data,
                        cs_dbs_info->down_skip = 0;
                        cs_dbs_info->enable = 1;
                        cs_dbs_info->requested_freq = policy->cur;
-                       cpufreq_register_notifier(cs_ops->notifier_block,
-                                       CPUFREQ_TRANSITION_NOTIFIER);
 
-                       dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
-                               jiffies_to_usecs(10);
+                       if (!policy->governor->initialized) {
+                               cpufreq_register_notifier(cs_ops->notifier_block,
+                                               CPUFREQ_TRANSITION_NOTIFIER);
+
+                               dbs_data->min_sampling_rate =
+                                       MIN_SAMPLING_RATE_RATIO *
+                                       jiffies_to_usecs(10);
+                       }
                } else {
                        od_dbs_info->rate_mult = 1;
                        od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
                        od_ops->powersave_bias_init_cpu(cpu);
-                       od_tuners->io_is_busy = od_ops->io_busy();
+
+                       if (!policy->governor->initialized)
+                               od_tuners->io_is_busy = od_ops->io_busy();
                }
 
+               if (policy->governor->initialized)
+                       goto unlock;
+
+               /* policy latency is in nS. Convert it to uS first */
+               latency = policy->cpuinfo.transition_latency / 1000;
+               if (latency == 0)
+                       latency = 1;
+
                /* Bring kernel and HW constraints together */
                dbs_data->min_sampling_rate = max(dbs_data->min_sampling_rate,
                                MIN_LATENCY_MULTIPLIER * latency);
                *sampling_rate = max(dbs_data->min_sampling_rate, latency *
                                LATENCY_MULTIPLIER);
+unlock:
                mutex_unlock(&dbs_data->mutex);
 
                /* Initiate timer time stamp */
@@ -284,11 +315,13 @@ int cpufreq_governor_dbs(struct dbs_data *dbs_data,
                mutex_lock(&dbs_data->mutex);
                mutex_destroy(&cpu_cdbs->timer_mutex);
 
-               sysfs_remove_group(cpufreq_global_kobject,
-                               dbs_data->attr_group);
-               if (dbs_data->governor == GOV_CONSERVATIVE)
-                       cpufreq_unregister_notifier(cs_ops->notifier_block,
-                                       CPUFREQ_TRANSITION_NOTIFIER);
+               if (policy->governor->initialized == 1) {
+                       sysfs_remove_group(cpufreq_global_kobject,
+                                       dbs_data->attr_group);
+                       if (dbs_data->governor == GOV_CONSERVATIVE)
+                               cpufreq_unregister_notifier(cs_ops->notifier_block,
+                                               CPUFREQ_TRANSITION_NOTIFIER);
+               }
                mutex_unlock(&dbs_data->mutex);
 
                break;