OSDN Git Service

Merge 4.4.123 into android-4.4
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / drivers / cpufreq / cpufreq.c
index c0fb6f1..d94b77a 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/cpu.h>
 #include <linux/cpufreq.h>
+#include <linux/cpufreq_times.h>
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/init.h>
@@ -29,6 +30,9 @@
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
 #include <linux/tick.h>
+#ifdef CONFIG_SMP
+#include <linux/sched.h>
+#endif
 #include <trace/events/power.h>
 
 static LIST_HEAD(cpufreq_policy_list);
@@ -154,6 +158,12 @@ bool have_governor_per_policy(void)
 }
 EXPORT_SYMBOL_GPL(have_governor_per_policy);
 
+bool cpufreq_driver_is_slow(void)
+{
+       return !(cpufreq_driver->flags & CPUFREQ_DRIVER_FAST);
+}
+EXPORT_SYMBOL_GPL(cpufreq_driver_is_slow);
+
 struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)
 {
        if (have_governor_per_policy())
@@ -347,6 +357,50 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
 #endif
 }
 
+/*********************************************************************
+ *               FREQUENCY INVARIANT CPU CAPACITY                    *
+ *********************************************************************/
+
+static DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE;
+static DEFINE_PER_CPU(unsigned long, max_freq_scale) = SCHED_CAPACITY_SCALE;
+
+static void
+scale_freq_capacity(struct cpufreq_policy *policy, struct cpufreq_freqs *freqs)
+{
+       unsigned long cur = freqs ? freqs->new : policy->cur;
+       unsigned long scale = (cur << SCHED_CAPACITY_SHIFT) / policy->max;
+       struct cpufreq_cpuinfo *cpuinfo = &policy->cpuinfo;
+       int cpu;
+
+       pr_debug("cpus %*pbl cur/cur max freq %lu/%u kHz freq scale %lu\n",
+                cpumask_pr_args(policy->cpus), cur, policy->max, scale);
+
+       for_each_cpu(cpu, policy->cpus)
+               per_cpu(freq_scale, cpu) = scale;
+
+       if (freqs)
+               return;
+
+       scale = (policy->max << SCHED_CAPACITY_SHIFT) / cpuinfo->max_freq;
+
+       pr_debug("cpus %*pbl cur max/max freq %u/%u kHz max freq scale %lu\n",
+                cpumask_pr_args(policy->cpus), policy->max, cpuinfo->max_freq,
+                scale);
+
+       for_each_cpu(cpu, policy->cpus)
+               per_cpu(max_freq_scale, cpu) = scale;
+}
+
+unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu)
+{
+       return per_cpu(freq_scale, cpu);
+}
+
+unsigned long cpufreq_scale_max_freq_capacity(int cpu)
+{
+       return per_cpu(max_freq_scale, cpu);
+}
+
 static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
                struct cpufreq_freqs *freqs, unsigned int state)
 {
@@ -384,6 +438,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
                pr_debug("FREQ: %lu - CPU: %lu\n",
                         (unsigned long)freqs->new, (unsigned long)freqs->cpu);
                trace_cpu_frequency(freqs->new, freqs->cpu);
+               cpufreq_times_record_transition(freqs);
                srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
                                CPUFREQ_POSTCHANGE, freqs);
                if (likely(policy) && likely(policy->cpu == freqs->cpu))
@@ -423,6 +478,9 @@ static void cpufreq_notify_post_transition(struct cpufreq_policy *policy,
 void cpufreq_freq_transition_begin(struct cpufreq_policy *policy,
                struct cpufreq_freqs *freqs)
 {
+#ifdef CONFIG_SMP
+       int cpu;
+#endif
 
        /*
         * Catch double invocations of _begin() which lead to self-deadlock.
@@ -450,6 +508,12 @@ wait:
 
        spin_unlock(&policy->transition_lock);
 
+       scale_freq_capacity(policy, freqs);
+#ifdef CONFIG_SMP
+       for_each_cpu(cpu, policy->cpus)
+               trace_cpu_capacity(capacity_curr_of(cpu), cpu);
+#endif
+
        cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE);
 }
 EXPORT_SYMBOL_GPL(cpufreq_freq_transition_begin);
@@ -469,6 +533,38 @@ void cpufreq_freq_transition_end(struct cpufreq_policy *policy,
 }
 EXPORT_SYMBOL_GPL(cpufreq_freq_transition_end);
 
+/**
+ * cpufreq_driver_resolve_freq - Map a target frequency to a driver-supported
+ * one.
+ * @target_freq: target frequency to resolve.
+ *
+ * The target to driver frequency mapping is cached in the policy.
+ *
+ * Return: Lowest driver-supported frequency greater than or equal to the
+ * given target_freq, subject to policy (min/max) and driver limitations.
+ */
+unsigned int cpufreq_driver_resolve_freq(struct cpufreq_policy *policy,
+                                        unsigned int target_freq)
+{
+       target_freq = clamp_val(target_freq, policy->min, policy->max);
+       policy->cached_target_freq = target_freq;
+
+       if (cpufreq_driver->target_index) {
+               int idx, rv;
+
+               rv = cpufreq_frequency_table_target(policy, policy->freq_table,
+                                                   target_freq,
+                                                   CPUFREQ_RELATION_L,
+                                                   &idx);
+               if (rv)
+                       return target_freq;
+               policy->cached_resolved_idx = idx;
+               return policy->freq_table[idx].frequency;
+        }
+
+       return target_freq;
+}
+EXPORT_SYMBOL_GPL(cpufreq_driver_resolve_freq);
 
 /*********************************************************************
  *                          SYSFS INTERFACE                          *
@@ -1254,6 +1350,7 @@ static int cpufreq_online(unsigned int cpu)
                        goto out_exit_policy;
                blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
                                CPUFREQ_CREATE_POLICY, policy);
+               cpufreq_times_create_policy(policy);
 
                write_lock_irqsave(&cpufreq_driver_lock, flags);
                list_add(&policy->policy_list, &cpufreq_policy_list);
@@ -2137,8 +2234,11 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
        blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
                        CPUFREQ_NOTIFY, new_policy);
 
+       scale_freq_capacity(new_policy, NULL);
+
        policy->min = new_policy->min;
        policy->max = new_policy->max;
+       trace_cpu_frequency_limits(policy->max, policy->min, policy->cpu);
 
        pr_debug("new min and max freqs are %u - %u kHz\n",
                 policy->min, policy->max);