ARM: tegra: power: Apply down delay to balancing CPUs
Alex Frid [Sun, 29 Apr 2012 06:25:39 +0000 (23:25 -0700)]
On Tegra3 secondary G-CPU may be turned off by auto-hotplug governor
in two cases: when overall CPU load is low enough to justify transition
to LP CPU, or when CPU cores usage by the scheduler is unbalanced
(skewed). In the former case down delay (currently 2sec) was inserted
before the core is turned Off. In the latter case the up delay (100ms)
was used, i.e., the same delay applied to balancing cores regardless
of the On/Off direction.

This commit would apply down delay when turning core Off in both cases
above, and keep using up delay only for turning core On.

Change-Id: Id545f8d48cbf380e24824a5adfe045ff68c1f39c
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/99708
Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>

arch/arm/mach-tegra/cpu-tegra3.c

index d953527..374a271 100644 (file)
@@ -217,6 +217,8 @@ static void tegra_auto_hotplug_work_func(struct work_struct *work)
 {
        bool up = false;
        unsigned int cpu = nr_cpu_ids;
+       unsigned long now = jiffies;
+       static unsigned long last_change_time;
 
        mutex_lock(tegra3_cpu_lock);
 
@@ -228,19 +230,17 @@ static void tegra_auto_hotplug_work_func(struct work_struct *work)
                cpu = tegra_get_slowest_cpu_n();
                if (cpu < nr_cpu_ids) {
                        up = false;
-                       queue_delayed_work(
-                               hotplug_wq, &hotplug_work, down_delay);
-                       hp_stats_update(cpu, false);
                } else if (!is_lp_cluster() && !no_lp) {
                        if(!clk_set_parent(cpu_clk, cpu_lp_clk)) {
                                hp_stats_update(CONFIG_NR_CPUS, true);
                                hp_stats_update(0, false);
                                /* catch-up with governor target speed */
                                tegra_cpu_set_speed_cap(NULL);
-                       } else
-                               queue_delayed_work(
-                                       hotplug_wq, &hotplug_work, down_delay);
+                               break;
+                       }
                }
+               queue_delayed_work(
+                       hotplug_wq, &hotplug_work, down_delay);
                break;
        case TEGRA_HP_UP:
                if (is_lp_cluster() && !no_lp) {
@@ -255,18 +255,14 @@ static void tegra_auto_hotplug_work_func(struct work_struct *work)
                        /* cpu speed is up and balanced - one more on-line */
                        case TEGRA_CPU_SPEED_BALANCED:
                                cpu = cpumask_next_zero(0, cpu_online_mask);
-                               if (cpu < nr_cpu_ids) {
+                               if (cpu < nr_cpu_ids)
                                        up = true;
-                                       hp_stats_update(cpu, true);
-                               }
                                break;
                        /* cpu speed is up, but skewed - remove one core */
                        case TEGRA_CPU_SPEED_SKEWED:
                                cpu = tegra_get_slowest_cpu_n();
-                               if (cpu < nr_cpu_ids) {
+                               if (cpu < nr_cpu_ids)
                                        up = false;
-                                       hp_stats_update(cpu, false);
-                               }
                                break;
                        /* cpu speed is up, but under-utilized - do nothing */
                        case TEGRA_CPU_SPEED_BIASED:
@@ -281,6 +277,14 @@ static void tegra_auto_hotplug_work_func(struct work_struct *work)
                pr_err("%s: invalid tegra hotplug state %d\n",
                       __func__, hp_state);
        }
+
+       if (!up && ((now - last_change_time) < down_delay))
+                       cpu = nr_cpu_ids;
+
+       if (cpu < nr_cpu_ids) {
+               last_change_time = now;
+               hp_stats_update(cpu, up);
+       }
        mutex_unlock(tegra3_cpu_lock);
 
        if (cpu < nr_cpu_ids) {