diff options
author | Alex Frid <afrid@nvidia.com> | 2012-04-28 23:25:39 -0700 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2012-05-01 17:01:45 -0700 |
commit | ce8006db5ef53f32d0ce0d4f65f5537b3fb320ee (patch) | |
tree | 57d5c8d4c92878a8cd6857519ed90f5bc88ef139 | |
parent | 1827824d541eef3899122e9040e0662042d935d1 (diff) |
ARM: tegra: power: Apply down delay to balancing CPUs
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: I3ac01c4df833eaf020966d561ec4b9802e25b529
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/99737
Tested-by: Jay Cheng <jacheng@nvidia.com>
Reviewed-by: Prajakta Gudadhe <pgudadhe@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/cpu-tegra3.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/arch/arm/mach-tegra/cpu-tegra3.c b/arch/arm/mach-tegra/cpu-tegra3.c index 76ff94435a13..f002803134a8 100644 --- a/arch/arm/mach-tegra/cpu-tegra3.c +++ b/arch/arm/mach-tegra/cpu-tegra3.c @@ -214,6 +214,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); @@ -225,19 +227,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) { @@ -252,18 +252,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: @@ -278,6 +274,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) { |