]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00215955 cpufreq interactive mx6: set cpufreq lowest point if cpu idling
authorRobin Gong <B38343@freescale.com>
Fri, 6 Jul 2012 05:07:25 +0000 (13:07 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:34:58 +0000 (08:34 +0200)
Consider the below scenario:  there is one CPU enter idle state before
switch happen, and the CPU frequency is set on high point(1G with userspace
cpufreq profile). After cpufreq profile is switched to interactive, all of the
cpus's target_freq will be set to the current CPU frequency  1G. Then after one
sample window, interactive profile will revalue the current cpu loading in
every cpu(except idle cpu), and get the desired frequency and compared with
target_freq to decide up or down frequency.  Until all of cpus's target_freq
is lower than desired frequency , down frequency will happen. But the idle
CPU's frequency has been set on 1G , so cpu frequency miss the chance to set
lower cpu frequency , although there is no loading in all of cpus.CPU frequency
will be down unless the idled CPU exit idle to revalue cpu loading and get the
right target_freq, in the worst case, it will never happen.

Now we can do this:
If we judge cpu idle state and set taget_freq to lowest frequency when switch
to interactive, then CPU frequency modify will never be blocked on idled CPU.
Signed-off-by: Robin Gong <B38343@freescale.com>
drivers/cpufreq/cpufreq_interactive.c

index c3bc7533df07fad3df44dbea1ff953f1178992d7..2db752c1d346d7bea78bd77a833ef382bbd0ab7c 100644 (file)
@@ -227,7 +227,6 @@ static void cpufreq_interactive_timer(unsigned long data)
        }
 
        new_freq = pcpu->freq_table[index].frequency;
-
        if (pcpu->target_freq == new_freq)
                goto rearm_if_notmax;
 
@@ -295,11 +294,10 @@ static void cpufreq_interactive_idle_start(void)
                &per_cpu(cpuinfo, smp_processor_id());
        int pending;
 
-       if (!pcpu->governor_enabled)
-               return;
-
        pcpu->idling = 1;
        smp_wmb();
+       if (!pcpu->governor_enabled)
+               return;
        pending = timer_pending(&pcpu->cpu_timer);
 
        if (pcpu->target_freq != pcpu->policy->min) {
@@ -412,11 +410,9 @@ static int cpufreq_interactive_up_task(void *data)
                        for_each_online_cpu(j) {
                                struct cpufreq_interactive_cpuinfo *pjcpu =
                                        &per_cpu(cpuinfo, j);
-
                                if (pjcpu->target_freq > max_freq)
                                        max_freq = pjcpu->target_freq;
                        }
-
                        if (max_freq != pcpu->policy->cur)
                                __cpufreq_driver_target(pcpu->policy,
                                                        max_freq,
@@ -640,7 +636,11 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
                for_each_cpu(j, policy->cpus) {
                        pcpu = &per_cpu(cpuinfo, j);
                        pcpu->policy = policy;
-                       pcpu->target_freq = policy->cur;
+                       if (pcpu->idling)
+                               pcpu->target_freq = policy->min;
+                       else
+                               pcpu->target_freq = policy->cur;
+
                        pcpu->freq_table = freq_table;
                        pcpu->freq_change_time_in_idle =
                                get_cpu_idle_time_us(j,