]> xenbits.xensource.com Git - people/aperard/linux-chromebook.git/commitdiff
CHROMIUM: cpufreq_interactive: correct cpu idle time calculation
authorSam Leffler <sleffler@chromium.org>
Mon, 12 Nov 2012 17:12:56 +0000 (09:12 -0800)
committerGerrit <chrome-bot@google.com>
Wed, 14 Nov 2012 01:59:51 +0000 (17:59 -0800)
Each cpu has a timer that tracks load and decides whether to adjust the
clock for that processor.  The timer callback may, however, execute on
any cpu, not just the one it manages.  Fix the idle time calculation to
take this into consideration--it was assuming smp_processor_id() returned
the cpu id of the processor to manage, causing incorrect decisions.

Signed-off-by: sleffler@chromium.org
BUG=none
TEST=run cpu intensive benchmark like octane on a multi-core system; check trace results and note that sometimes v8 runs for extended times on cpu operating at low freq (contributing to poor score)

Change-Id: I2b5c21b5d8cae31679e844ac67037cc760c5dfc0
Reviewed-on: https://gerrit.chromium.org/gerrit/37830
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
Reviewed-by: Sameer Nanda <snanda@chromium.org>
Tested-by: Sam Leffler <sleffler@chromium.org>
Commit-Ready: Sam Leffler <sleffler@chromium.org>

drivers/cpufreq/cpufreq_interactive.c

index 72a362715e2e1a65584d07e8bbf5c904d15669ea..7e7f439c73c87111675df41b7affc3b1bae50477 100644 (file)
@@ -43,6 +43,7 @@ struct cpufreq_interactive_cpuinfo {
        u64 time_in_idle;
        u64 idle_exit_time;
        u64 timer_run_time;
+       int cpu_id;
        int idling;
        u64 target_set_time;
        u64 target_set_time_in_idle;
@@ -120,8 +121,8 @@ struct cpufreq_governor cpufreq_gov_interactive = {
 
 static void rearm_idle_timer(struct cpufreq_interactive_cpuinfo *pcpu)
 {
-       pcpu->time_in_idle = get_cpu_idle_time_us(
-           smp_processor_id(), &pcpu->idle_exit_time);
+       pcpu->time_in_idle = get_cpu_idle_time_us(pcpu->cpu_id,
+           &pcpu->idle_exit_time);
        mod_timer(&pcpu->cpu_timer, jiffies + usecs_to_jiffies(timer_rate));
 }
 
@@ -145,6 +146,8 @@ static void del_idle_timer(struct cpufreq_interactive_cpuinfo *pcpu)
 
 static void cpufreq_interactive_timer(unsigned long data)
 {
+       struct cpufreq_interactive_cpuinfo *pcpu = data;
+       int cpu_id = pcpu->cpu_id;
        unsigned int delta_idle;
        unsigned int delta_time;
        int cpu_load;
@@ -152,8 +155,6 @@ static void cpufreq_interactive_timer(unsigned long data)
        int need_wakeup;
        u64 time_in_idle;
        u64 idle_exit_time;
-       struct cpufreq_interactive_cpuinfo *pcpu =
-               &per_cpu(cpuinfo, data);
        u64 now_idle;
        unsigned int new_freq;
        unsigned int index;
@@ -175,7 +176,7 @@ static void cpufreq_interactive_timer(unsigned long data)
         */
        time_in_idle = pcpu->time_in_idle;
        idle_exit_time = pcpu->idle_exit_time;
-       now_idle = get_cpu_idle_time_us(data, &pcpu->timer_run_time);
+       now_idle = get_cpu_idle_time_us(cpu_id, &pcpu->timer_run_time);
        smp_wmb();
 
        /* If we raced with cancelling a timer, skip. */
@@ -227,9 +228,8 @@ static void cpufreq_interactive_timer(unsigned long data)
                            new_freq > hispeed_freq &&
                            pcpu->timer_run_time - pcpu->hispeed_validate_time
                            < above_hispeed_delay_val) {
-                               trace_cpufreq_interactive_notyet(data, cpu_load,
-                                                                pcpu->target_freq,
-                                                                new_freq);
+                               trace_cpufreq_interactive_notyet(cpu_id,
+                                   cpu_load, pcpu->target_freq, new_freq);
                                goto rearm;
                        }
                }
@@ -244,7 +244,7 @@ static void cpufreq_interactive_timer(unsigned long data)
                                           new_freq, CPUFREQ_RELATION_H,
                                           &index)) {
                pr_warn_once("timer %d: cpufreq_frequency_table_target error\n",
-                            (int) data);
+                            (int) cpu_id);
                goto rearm;
        }
 
@@ -257,7 +257,7 @@ static void cpufreq_interactive_timer(unsigned long data)
        if (new_freq < pcpu->floor_freq) {
                if (pcpu->timer_run_time - pcpu->floor_validate_time
                    < min_sample_time) {
-                       trace_cpufreq_interactive_notyet(data, cpu_load,
+                       trace_cpufreq_interactive_notyet(cpu_id, cpu_load,
                                                         pcpu->target_freq,
                                                         new_freq);
                        goto rearm;
@@ -266,15 +266,15 @@ static void cpufreq_interactive_timer(unsigned long data)
 
        spin_lock_irqsave(&updown_state_lock, flags);
        if (pcpu->target_freq != new_freq) {
-               trace_cpufreq_interactive_target(data, cpu_load,
+               trace_cpufreq_interactive_target(cpu_id, cpu_load,
                                                 pcpu->target_freq, new_freq);
                pcpu->target_set_time_in_idle = now_idle;
                pcpu->target_freq = new_freq;
                pcpu->target_set_time = pcpu->timer_run_time;
-               cpumask_set_cpu(data, &updown_cpumask);
+               cpumask_set_cpu(cpu_id, &updown_cpumask);
                need_wakeup = 1;
        } else {
-               trace_cpufreq_interactive_already(data, cpu_load,
+               trace_cpufreq_interactive_already(cpu_id, cpu_load,
                                                  pcpu->target_freq, new_freq);
                need_wakeup = 0;
        }
@@ -934,9 +934,10 @@ static int __init cpufreq_interactive_init(void)
        /* Initalize per-cpu timers */
        for_each_possible_cpu(i) {
                pcpu = &per_cpu(cpuinfo, i);
+               pcpu->cpu_id = i;
                init_timer(&pcpu->cpu_timer);
                pcpu->cpu_timer.function = cpufreq_interactive_timer;
-               pcpu->cpu_timer.data = i;
+               pcpu->cpu_timer.data = pcpu;
        }
 
        spin_lock_init(&updown_state_lock);