]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
ARM: tegra: Disable cpuquiet governor when idle
authorSai Gurrappadi <sgurrappadi@nvidia.com>
Thu, 8 May 2014 22:56:49 +0000 (15:56 -0700)
committerGerrit Code Review <gerrit2@nvidia.com>
Thu, 15 May 2014 22:57:31 +0000 (15:57 -0700)
The cpuquiet governor shouldn't load the system when in idle so stop the
governor from running when on single core at low frequencies as governed by
idle_bottom_freq.

Bug 200002511

Change-Id: I1fa9e2c320035bab0c4be6a032f53d02b3f0f3ca
Signed-off-by: Sai Gurrappadi <sgurrappadi@nvidia.com>
arch/arm/mach-tegra/cpu-tegra.h
arch/arm/mach-tegra/cpuquiet.c

index 0fd8b731cb2fef24a0a87da5408cc5106e44c414..9887cf92f09a238d5a71903617b7202889a471d2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/arm/mach-tegra/cpu-tegra.h
  *
- * Copyright (c) 2011-2013, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2011-2014, NVIDIA Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -37,14 +37,8 @@ unsigned long tegra_cpu_highest_speed(void);
 #if defined(CONFIG_TEGRA_AUTO_HOTPLUG) && !defined(CONFIG_ARCH_TEGRA_2x_SOC)
 int tegra_auto_hotplug_init(struct mutex *cpulock);
 void tegra_auto_hotplug_exit(void);
-#ifdef CONFIG_TEGRA_CLUSTER_CONTROL
 void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend);
 #else
-static inline void tegra_auto_hotplug_governor(unsigned int cpu_freq,
-                                               bool suspend)
-{}
-#endif
-#else
 static inline int tegra_auto_hotplug_init(struct mutex *cpu_lock)
 { return 0; }
 static inline void tegra_auto_hotplug_exit(void)
index 8767980c33b4cf221870607914f4ca6158f24b92..93b6561203ccb4cc0629da12b7d83bad6ac29515 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Cpuquiet driver for Tegra CPUs
  *
- * Copyright (c) 2012-2013 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2012-2014, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -68,11 +68,11 @@ static wait_queue_head_t wait_cpu;
  */
 static int no_lp;
 static bool enable;
+static unsigned int idle_bottom_freq;
 #ifdef CONFIG_TEGRA_CLUSTER_CONTROL
 static unsigned long up_delay;
 static unsigned long down_delay;
 static unsigned int idle_top_freq;
-static unsigned int idle_bottom_freq;
 static struct clk *cpu_clk;
 static struct clk *cpu_g_clk;
 static struct clk *cpu_lp_clk;
@@ -244,6 +244,9 @@ static void __update_target_cluster(unsigned int cpu_freq, bool suspend)
                }
        }
 }
+#else
+static inline void __update_target_cluster(unsigned int cpu_freq, bool suspend)
+{ }
 #endif
 
 static int update_core_config(unsigned int cpunumber, bool up)
@@ -257,7 +260,6 @@ static int update_core_config(unsigned int cpunumber, bool up)
                return -EINVAL;
        }
 
-
        if (up) {
                cpumask_set_cpu(cpunumber, &cr_online_requests);
                cpumask_clear_cpu(cpunumber, &cr_offline_requests);
@@ -524,22 +526,45 @@ static int max_cpus_notify(struct notifier_block *nb, unsigned long n, void *p)
        return NOTIFY_OK;
 }
 
-#ifdef CONFIG_TEGRA_CLUSTER_CONTROL
+#ifndef CONFIG_TEGRA_CLUSTER_CONTROL
+/* Must be called with tegra_cpu_lock held */
+static void __idle_stop_governor(unsigned int freq)
+{
+       if (cpq_state == TEGRA_CPQ_DISABLED)
+               return;
+
+       if (freq <= idle_bottom_freq && num_online_cpus() == 1)
+               cpuquiet_device_busy();
+       else
+               cpuquiet_device_free();
+}
+#endif
+
 static int __cpuinit cpu_online_notify(struct notifier_block *nfb,
                                        unsigned long action, void *hcpu)
 {
+       unsigned int freq;
+
        switch (action) {
        case CPU_POST_DEAD:
                if (num_online_cpus() == 1) {
                        mutex_lock(tegra_cpu_lock);
-                       __update_target_cluster(tegra_getspeed(0), false);
+                       freq = tegra_getspeed(0);
+                       __update_target_cluster(freq, false);
+#ifndef CONFIG_TEGRA_CLUSTER_CONTROL
+                       __idle_stop_governor(freq);
+#endif
                        mutex_unlock(tegra_cpu_lock);
                }
                break;
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
                mutex_lock(tegra_cpu_lock);
-               __update_target_cluster(tegra_getspeed(0), false);
+               freq = tegra_getspeed(0);
+               __update_target_cluster(freq, false);
+#ifndef CONFIG_TEGRA_CLUSTER_CONTROL
+               __idle_stop_governor(freq);
+#endif
                mutex_unlock(tegra_cpu_lock);
                break;
        }
@@ -547,6 +572,7 @@ static int __cpuinit cpu_online_notify(struct notifier_block *nfb,
        return NOTIFY_OK;
 }
 
+#ifdef CONFIG_TEGRA_CLUSTER_CONTROL
 /* must be called with tegra_cpu_lock held */
 void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend)
 {
@@ -570,11 +596,16 @@ void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend)
 
        __update_target_cluster(cpu_freq, suspend);
 }
+#else
+void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend)
+{
+       __idle_stop_governor(cpu_freq);
+}
+#endif
 
 static struct notifier_block __cpuinitdata cpu_online_notifier = {
        .notifier_call = cpu_online_notify,
 };
-#endif
 
 static struct notifier_block min_cpus_notifier = {
        .notifier_call = min_cpus_notify,
@@ -652,10 +683,10 @@ ssize_t store_no_lp(struct cpuquiet_attribute *attr,
 
 CPQ_ATTRIBUTE_CUSTOM(no_lp, 0644, show_int_attribute, store_no_lp);
 CPQ_BASIC_ATTRIBUTE(idle_top_freq, 0644, uint);
-CPQ_BASIC_ATTRIBUTE(idle_bottom_freq, 0644, uint);
 CPQ_ATTRIBUTE(up_delay, 0644, ulong, delay_callback);
 CPQ_ATTRIBUTE(down_delay, 0644, ulong, delay_callback);
 #endif
+CPQ_BASIC_ATTRIBUTE(idle_bottom_freq, 0644, uint);
 CPQ_ATTRIBUTE(hotplug_timeout, 0644, ulong, delay_callback);
 CPQ_ATTRIBUTE(enable, 0644, bool, enable_callback);
 
@@ -665,8 +696,8 @@ static struct attribute *tegra_auto_attributes[] = {
        &up_delay_attr.attr,
        &down_delay_attr.attr,
        &idle_top_freq_attr.attr,
-       &idle_bottom_freq_attr.attr,
 #endif
+       &idle_bottom_freq_attr.attr,
        &enable_attr.attr,
        &hotplug_timeout_attr.attr,
        NULL,
@@ -841,8 +872,11 @@ int __cpuinit tegra_auto_hotplug_init(struct mutex *cpulock)
        if (pm_qos_add_notifier(PM_QOS_MAX_ONLINE_CPUS, &max_cpus_notifier))
                pr_err("%s: Failed to register max cpus PM QoS notifier\n",
                        __func__);
-#ifdef CONFIG_TEGRA_CLUSTER_CONTROL
+
        register_hotcpu_notifier(&cpu_online_notifier);
+
+#ifndef CONFIG_TEGRA_CLUSTER_CONTROL
+       idle_bottom_freq = 714000;
 #endif
 
        err = cpuquiet_register_driver(&tegra_cpuquiet_driver);