ARM: tegra: Decouple edp and cpuquiet
Sai Gurrappadi [Wed, 20 Nov 2013 00:44:25 +0000 (16:44 -0800)]
Removed tegra_cpu_edp_favor_up/down api. EDP now requests a
PM_QOS_MAX_ONLINE_CPUS request to allow for the configuration that gives
the maximum number of MIPS given current temperature and the edp tables.

Bug 1160651

Change-Id: I2639a0f5f05901809e6249170733912b593f7549
Signed-off-by: Sai Gurrappadi <sgurrappadi@nvidia.com>
Reviewed-on: http://git-master/r/333133
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>

arch/arm/mach-tegra/cpu-tegra.c
arch/arm/mach-tegra/cpu-tegra.h
arch/arm/mach-tegra/cpuquiet.c

index 9382e88..20b8aa5 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/debugfs.h>
 #include <linux/cpu.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_qos.h>
 
 #include <mach/edp.h>
 
@@ -193,6 +194,7 @@ static bool system_edp_alarm;
 static int edp_thermal_index;
 static cpumask_t edp_cpumask;
 static unsigned int edp_limit;
+static struct pm_qos_request edp_max_cpus;
 
 unsigned int tegra_get_edp_limit(int *get_edp_thermal_index)
 {
@@ -216,14 +218,10 @@ static unsigned int edp_predict_limit(unsigned int cpus)
        return limit;
 }
 
-/* Must be called while holding cpu_tegra_lock */
-static void edp_update_limit(void)
+static unsigned int get_edp_freq_limit(unsigned int nr_cpus)
 {
-       unsigned int limit = edp_predict_limit(cpumask_weight(&edp_cpumask));
-       BUG_ON(!mutex_is_locked(&tegra_cpu_lock));
-#ifdef CONFIG_TEGRA_EDP_EXACT_FREQ
-       edp_limit = limit;
-#else
+       unsigned int limit = edp_predict_limit(nr_cpus);
+#ifndef CONFIG_TEGRA_EDP_EXACT_FREQ
        unsigned int i;
        for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
                if (freq_table[i].frequency > limit) {
@@ -231,8 +229,51 @@ static void edp_update_limit(void)
                }
        }
        BUG_ON(i == 0); /* min freq above the limit or table empty */
-       edp_limit = freq_table[i-1].frequency;
+       limit = freq_table[i-1].frequency;
 #endif
+       return limit;
+}
+
+/*
+ * Returns the ideal nr of cpus to have online for maximum performance given
+ * edp constraints at the current temperature
+ */
+static int get_edp_max_cpus(void)
+{
+       unsigned int i, limit;
+       unsigned int max_mips = 0;
+       int max_nr_cpus = PM_QOS_DEFAULT_VALUE;
+
+       for (i = 1; i <= num_possible_cpus(); i++) {
+               limit = get_edp_freq_limit(i);
+               if (limit * i >= max_mips) {
+                       max_mips = limit * i;
+                       max_nr_cpus = i;
+               }
+       }
+       return max_nr_cpus;
+}
+
+/*
+ * Shouldn't be called with tegra_cpu_lock held. Will result in a deadlock
+ * otherwise
+ */
+static void edp_update_max_cpus(void)
+{
+       unsigned int max_cpus = get_edp_max_cpus();
+
+       if (!pm_qos_request_active(&edp_max_cpus))
+               pm_qos_add_request(&edp_max_cpus, PM_QOS_MAX_ONLINE_CPUS,
+                                  max_cpus);
+       else
+               pm_qos_update_request(&edp_max_cpus, max_cpus);
+}
+
+/* Must be called while holding cpu_tegra_lock */
+static void edp_update_limit(void)
+{
+       BUG_ON(!mutex_is_locked(&tegra_cpu_lock));
+       edp_limit = get_edp_freq_limit(cpumask_weight(&edp_cpumask));
 }
 
 static unsigned int edp_governor_speed(unsigned int requested_speed)
@@ -273,6 +314,8 @@ int tegra_edp_set_cur_state(struct thermal_cooling_device *cdev,
        tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, false, 0);
        mutex_unlock(&tegra_cpu_lock);
 
+       edp_update_max_cpus();
+
        return 0;
 }
 
@@ -314,40 +357,6 @@ int tegra_system_edp_alarm(bool alarm)
        return ret;
 }
 
-bool tegra_cpu_edp_favor_up(unsigned int n, int mp_overhead)
-{
-       unsigned int current_limit, next_limit;
-
-       if (n == 0)
-               return true;
-
-       if (n >= ARRAY_SIZE(cpu_edp_limits->freq_limits))
-               return false;
-
-       current_limit = edp_predict_limit(n);
-       next_limit = edp_predict_limit(n + 1);
-
-       return ((next_limit * (n + 1)) >=
-               (current_limit * n * (100 + mp_overhead) / 100));
-}
-
-bool tegra_cpu_edp_favor_down(unsigned int n, int mp_overhead)
-{
-       unsigned int current_limit, next_limit;
-
-       if (n <= 1)
-               return false;
-
-       if (n > ARRAY_SIZE(cpu_edp_limits->freq_limits))
-               return true;
-
-       current_limit = edp_predict_limit(n);
-       next_limit = edp_predict_limit(n - 1);
-
-       return ((next_limit * (n - 1) * (100 + mp_overhead) / 100)) >
-               (current_limit * n);
-}
-
 static int tegra_cpu_edp_notify(
        struct notifier_block *nb, unsigned long event, void *hcpu)
 {
index 9db09d6..9587e74 100644 (file)
@@ -48,16 +48,6 @@ static inline void tegra_auto_hotplug_governor(unsigned int cpu_freq,
 { }
 #endif
 
-#ifdef CONFIG_TEGRA_EDP_LIMITS
-bool tegra_cpu_edp_favor_up(unsigned int n, int mp_overhead);
-bool tegra_cpu_edp_favor_down(unsigned int n, int mp_overhead);
-#else
-static inline bool tegra_cpu_edp_favor_up(unsigned int n, int mp_overhead)
-{ return true; }
-static inline bool tegra_cpu_edp_favor_down(unsigned int n, int mp_overhead)
-{ return false; }
-#endif
-
 #ifdef CONFIG_CPU_FREQ
 int tegra_suspended_target(unsigned int target_freq);
 #else
index b85fdc1..3d690a4 100644 (file)
@@ -69,7 +69,6 @@ static bool enable;
 static unsigned long up_delay;
 static unsigned long down_delay;
 static unsigned long hotplug_timeout;
-static int mp_overhead = 10;
 static unsigned int idle_top_freq;
 static unsigned int idle_bottom_freq;
 
@@ -245,7 +244,6 @@ static void __update_target_cluster(unsigned int cpu_freq, bool suspend)
 static int update_core_config(unsigned int cpunumber, bool up)
 {
        int ret = 0;
-       unsigned int nr_cpus = num_online_cpus();
 
        mutex_lock(tegra_cpu_lock);
 
@@ -260,7 +258,7 @@ static int update_core_config(unsigned int cpunumber, bool up)
                cpumask_clear_cpu(cpunumber, &cr_offline_requests);
                if (is_lp_cluster())
                        ret = -EBUSY;
-               else if (tegra_cpu_edp_favor_up(nr_cpus, mp_overhead))
+               else
                        queue_work(cpuquiet_wq, &cpuquiet_work);
        } else {
                if (is_lp_cluster()) {
@@ -643,7 +641,6 @@ ssize_t store_no_lp(struct cpuquiet_attribute *attr,
 
 CPQ_BASIC_ATTRIBUTE(idle_top_freq, 0644, uint);
 CPQ_BASIC_ATTRIBUTE(idle_bottom_freq, 0644, uint);
-CPQ_BASIC_ATTRIBUTE(mp_overhead, 0644, int);
 CPQ_ATTRIBUTE_CUSTOM(no_lp, 0644, show_int_attribute, store_no_lp);
 CPQ_ATTRIBUTE(up_delay, 0644, ulong, delay_callback);
 CPQ_ATTRIBUTE(down_delay, 0644, ulong, delay_callback);
@@ -656,7 +653,6 @@ static struct attribute *tegra_auto_attributes[] = {
        &down_delay_attr.attr,
        &idle_top_freq_attr.attr,
        &idle_bottom_freq_attr.attr,
-       &mp_overhead_attr.attr,
        &enable_attr.attr,
        &hotplug_timeout_attr.attr,
        NULL,