rk312x, mali_400: make it more 'difficult' to dump down in mali_dvfs_list.
authorchenzhen <chenzhen@rock-chips.com>
Wed, 28 Oct 2015 08:45:04 +0000 (16:45 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Wed, 28 Oct 2015 09:18:10 +0000 (17:18 +0800)
Change-Id: If5fd646aa6ca7f7383db70c84ff71f1570fe23b1
Signed-off-by: chenzhen <chenzhen@rock-chips.com>
drivers/gpu/arm/mali400/mali/platform/rk30/mali_dvfs.c [changed mode: 0755->0644]
drivers/gpu/arm/mali400/mali/platform/rk30/mali_dvfs.h [changed mode: 0755->0644]

old mode 100755 (executable)
new mode 100644 (file)
index 26ca41c..a3d8de0
@@ -1,4 +1,4 @@
-/*
+/**
  * Rockchip SoC Mali-450 DVFS driver
  *
  * This program is free software; you can redistribute it and/or modify
@@ -6,9 +6,26 @@
  * published by the Free Software FoundatIon.
  */
 
+
+/* #define ENABLE_DEBUG_LOG */
+#include "custom_log.h"
+
 #include "mali_platform.h"
 #include "mali_dvfs.h"
 
+/*---------------------------------------------------------------------------*/
+
+/**
+ * 若 count_of_continuous_requests_to_jump_up_in_dvfs_level_table 达到 value,
+ * 将触发一次 current_dvfs_level jump_up.
+ */
+#define        NUM_OF_CONTINUOUS_REQUESTS_TO_TRIGGER_REAL_JUMPING_UP           (1)
+/**
+ * 若 count_of_continuous_requests_to_jump_down_in_dvfs_level_table 达到 value,
+ * 将触发一次 current_dvfs_level jump_down.
+ */
+#define NUM_OF_CONTINUOUS_REQUESTS_TO_TRIGGER_REAL_JUMPING_DOWN                (30)
+
 #define level0_min 0
 #define level0_max 70
 #define levelf_max 100
 #define dvfs_to_drv_data(dvfs) \
        container_of(dvfs, struct mali_platform_drv_data, dvfs)
 
+/*---------------------------------------------------------------------------*/
+
+static bool mali_dvfs_should_jump_up(const struct mali_dvfs *p_dvfs)
+{
+       return (p_dvfs->m_count_of_requests_to_jump_up
+               >= NUM_OF_CONTINUOUS_REQUESTS_TO_TRIGGER_REAL_JUMPING_UP);
+}
+
+static bool mali_dvfs_should_jump_down(const struct mali_dvfs *p_dvfs)
+{
+       return (p_dvfs->m_count_of_requests_to_jump_down
+               >= NUM_OF_CONTINUOUS_REQUESTS_TO_TRIGGER_REAL_JUMPING_DOWN);
+}
+
+/**
+ * .KP :
+ * work_to_handle_mali_utilization_event 的实现主体,
+ * 将根据 current_mali_utilization_data, 改变 current_dvfs_level.
+ */
 static void mali_dvfs_event_proc(struct work_struct *w)
 {
-       struct mali_dvfs *dvfs = work_to_dvfs(w);
+       struct mali_dvfs *dvfs = work_to_dvfs(w);/* mali_dvfs_context. */
        struct mali_platform_drv_data *drv_data = dvfs_to_drv_data(dvfs);
        unsigned int utilisation = dvfs->utilisation;
+       int ret = 0;
+       /* index_of_current_dvfs_level. */
        unsigned int level = dvfs->current_level;
+       /* current_dvfs_level. */
        const struct mali_fv_info *threshold = &drv_data->fv_info[level];
-       int ret;
-
+       /* utilization_in_percentage. */
        utilisation = utilisation * 100 / 256;
 
-       /* dev_dbg(drv_data->dev, "utilisation percent = %d\n", utilisation); */
-
-       if (utilisation > threshold->max &&
-           level < drv_data->fv_info_length - 1)
-               level += 1;
-       else if (level > 0 && utilisation < threshold->min)
-               level -= 1;
-       else
+       V("mali_utilization_in_percentage : %d; index_of_current_level : %d;"
+                       "min: %d, max : %d",
+         utilisation,
+         level,
+         threshold->min,
+         threshold->max);
+       V("num_of_requests_to_jump_up : %d; num_of_requests_to_jump_down : %d",
+         dvfs->m_count_of_requests_to_jump_up,
+         dvfs->m_count_of_requests_to_jump_down);
+
+       if (utilisation > threshold->max) {
+               dvfs->m_count_of_requests_to_jump_down = 0;
+
+               /* 若 current_dvfs_level 还 "有" 上跳的空间, 则... */
+               if (level < (drv_data->fv_info_length - 1)) {
+                       V("to count one request_to_jump_up.");
+                       dvfs->m_count_of_requests_to_jump_up++;
+
+                       /* 若足够触发一次 real_jump_up, 则... */
+                       if (mali_dvfs_should_jump_up(dvfs)) {
+                               V("to preset real_jump_up.");
+                               level += 1;
+
+                               dvfs->m_count_of_requests_to_jump_up = 0;
+
+                               goto MAKE_DVFS_LEVEL_UPDATE_EFFECTIVE;
+                       }
+                       /* 否则, 即还 "不" 足以 real_jump_up, 则... */
+                       else
+                               return;
+               }
+               /* 否则, 即 "没有" 上跳的空间了, 则... */
+               else
+                       return;
+       } else if (utilisation < (threshold->min)) {
+               dvfs->m_count_of_requests_to_jump_up = 0;
+
+               /* 若 current_dvfs_level 还有 下跳的空间, 则... */
+               if (level > 0) {
+                       V("to count one request_to_jump_down.");
+                       dvfs->m_count_of_requests_to_jump_down++;
+
+                       /* 若足够触发一次 real_jump_down, 则... */
+                       if (mali_dvfs_should_jump_down(dvfs)) {
+                               V("to preset real_jump_down.");
+                               level -= 1;
+
+                               dvfs->m_count_of_requests_to_jump_down = 0;
+
+                               goto MAKE_DVFS_LEVEL_UPDATE_EFFECTIVE;
+                       } else {
+                               return;
+                       }
+               }
+               /* 否则, 即 "没有" 下跳的空间了, 则... */
+               else
+                       return;
+       }
+       /* 否则,
+        * 即 mali_utilization 在 'min' 和 'max' 之间,
+        * 即 current_dvfs_level 合适, 则 ... */
+       else {
+               dvfs->m_count_of_requests_to_jump_up = 0;
+               dvfs->m_count_of_requests_to_jump_down = 0;
                return;
+       }
 
+       /*
        dev_dbg(drv_data->dev, "Setting dvfs level %u: freq = %lu Hz\n",
                level, drv_data->fv_info[level].freq);
+       */
 
+MAKE_DVFS_LEVEL_UPDATE_EFFECTIVE:
        ret = mali_set_level(drv_data->dev, level);
        if (ret) {
                dev_err(drv_data->dev, "set freq error, %d", ret);
@@ -54,6 +152,9 @@ static void mali_dvfs_event_proc(struct work_struct *w)
        }
 }
 
+/**
+ * 返回 mali_dvfs_facility 当前是否被使能.
+ */
 bool mali_dvfs_is_enabled(struct device *dev)
 {
        struct mali_platform_drv_data *drv_data = dev_get_drvdata(dev);
@@ -62,6 +163,9 @@ bool mali_dvfs_is_enabled(struct device *dev)
        return dvfs->enabled;
 }
 
+/**
+ * 使能 mali_dvfs_facility.
+ */
 void mali_dvfs_enable(struct device *dev)
 {
        struct mali_platform_drv_data *drv_data = dev_get_drvdata(dev);
@@ -70,6 +174,9 @@ void mali_dvfs_enable(struct device *dev)
        dvfs->enabled = true;
 }
 
+/**
+ * 禁用 mali_dvfs_facility.
+ */
 void mali_dvfs_disable(struct device *dev)
 {
        struct mali_platform_drv_data *drv_data = dev_get_drvdata(dev);
@@ -77,8 +184,15 @@ void mali_dvfs_disable(struct device *dev)
 
        dvfs->enabled = false;
        cancel_work_sync(&dvfs->work);
+
+       /* 使用 lowest_dvfs_level. */
+       if (0 != mali_set_level(dev, 0))
+               W("fail to set current_dvfs_level to index 0.");
 }
 
+/**
+ * 返回当前 mali_dvfs_context 中最后记录的 mali_utilization.
+ */
 unsigned int mali_dvfs_utilisation(struct device *dev)
 {
        struct mali_platform_drv_data *drv_data = dev_get_drvdata(dev);
@@ -87,18 +201,27 @@ unsigned int mali_dvfs_utilisation(struct device *dev)
        return dvfs->utilisation;
 }
 
+/**
+ * 根据当前的 mali_utilization_event, 对应调整 mali_dvfs_facility.
+ * 运行在 context_of_common_part_calling_back_mali_utilization_event 中.
+ */
 int mali_dvfs_event(struct device *dev, u32 utilisation)
 {
        struct mali_platform_drv_data *drv_data = dev_get_drvdata(dev);
        struct mali_dvfs *dvfs = &drv_data->dvfs;
 
        dvfs->utilisation = utilisation;
+       V("mali_utilization_in_percentage : %d", utilisation * 100 / 256);
 
-       if (dvfs->enabled)
+       if (dvfs->enabled) {
+               /* 将 work_to_handle_mali_utilization_event,
+                * 放置到 kernel_global_workqueue, 待执行. */
                schedule_work(&dvfs->work);
+       }
 
        return MALI_TRUE;
 }
+
 static void mali_dvfs_threshold(u32 div,
                                struct mali_platform_drv_data *drv_data)
 {
@@ -119,33 +242,35 @@ static void mali_dvfs_threshold(u32 div,
                        if (level == length - 1)
                                drv_data->fv_info[level].max = levelf_max;
                        else
-                               drv_data->fv_info[level].max =
-                                       drv_data->fv_info[pre_level].max
-                                       + div;
+                               drv_data->fv_info[level].max
+                               = drv_data->fv_info[pre_level].max + div;
 
-                       drv_data->fv_info[level].min =
-                               drv_data->fv_info[pre_level].max
+                       drv_data->fv_info[level].min
+                       = drv_data->fv_info[pre_level].max
                                * drv_data->fv_info[pre_level].freq
                                / drv_data->fv_info[level].freq;
 
-                       tmp =
-                               drv_data->fv_info[level].max
+                       tmp
+                       = drv_data->fv_info[level].max
                                - drv_data->fv_info[level].min;
                        drv_data->fv_info[level].min += mali_fix_float(tmp);
                }
 
-               dev_info(drv_data->dev,
-                        "freq: %lu, min_threshold: %d, max_threshold: %d\n",
+               dev_info(drv_data->dev, "freq: %lu, min_threshold: %d, max_threshold: %d\n",
                         drv_data->fv_info[level].freq,
                         drv_data->fv_info[level].min,
                         drv_data->fv_info[level].max);
        }
 }
 
+/*---------------------------------------------------------------------------*/
+
 int mali_dvfs_init(struct device *dev)
 {
        struct mali_platform_drv_data *drv_data = dev_get_drvdata(dev);
+       /*mali_dvfs_context. */
        struct mali_dvfs *dvfs = &drv_data->dvfs;
+       /* gpu_clk_freq_table. */
        struct cpufreq_frequency_table *freq_table;
        int i = 0;
        int div_dvfs;
@@ -157,6 +282,7 @@ int mali_dvfs_init(struct device *dev)
                return -1;
        }
 
+       /* 确定 len_of_avaialble_dvfs_level_list. */
        while (freq_table[i].frequency != CPUFREQ_TABLE_END) {
                drv_data->fv_info_length++;
                i++;
@@ -172,8 +298,10 @@ int mali_dvfs_init(struct device *dev)
                drv_data->fv_info[i].freq = freq_table[i].frequency * 1000;
 
        if (drv_data->fv_info_length > 1)
-               div_dvfs = round_up(((levelf_max - level0_max) /
-                                   (drv_data->fv_info_length-1)), 1);
+               div_dvfs
+               = round_up(((levelf_max - level0_max)
+                               / (drv_data->fv_info_length - 1)),
+                          1);
 
        mali_dvfs_threshold(div_dvfs, drv_data);
 
@@ -183,11 +311,15 @@ int mali_dvfs_init(struct device *dev)
 
        drv_data->dvfs.current_level = 0;
 
-       dev_info(dev, "initial freq = %lu\n", dvfs_clk_get_rate(drv_data->clk));
+       dev_info(dev, "initial freq = %lu\n",
+                dvfs_clk_get_rate(drv_data->clk));
 
        INIT_WORK(&dvfs->work, mali_dvfs_event_proc);
        dvfs->enabled = true;
 
+       dvfs->m_count_of_requests_to_jump_up = 0;
+       dvfs->m_count_of_requests_to_jump_down = 0;
+
        return 0;
 }
 
@@ -196,6 +328,10 @@ void mali_dvfs_term(struct device *dev)
        struct mali_platform_drv_data *drv_data = dev_get_drvdata(dev);
        struct mali_dvfs *dvfs = &drv_data->dvfs;
 
+       dvfs->m_count_of_requests_to_jump_up = 0;
+       dvfs->m_count_of_requests_to_jump_down = 0;
+
        dvfs->enabled = false;
        cancel_work_sync(&dvfs->work);
 }
+
old mode 100755 (executable)
new mode 100644 (file)
index ddb68d9..bbf837f
 #ifndef _MALI_DVFS_H_
 #define _MALI_DVFS_H_
 
+
+/**
+ * mali_dvfs_context_t, context of mali_dvfs_facility.
+ */
 struct mali_dvfs {
+       /**
+        * work_to_handle_mali_utilization_event.
+        */
        struct work_struct work;
+       /**
+        * current_mali_utilization.
+        */
        unsigned int utilisation;
+       /**
+        * index_of_current_dvfs_level.
+        * current_dvfs_level 在 available_dvfs_level_list 中的 index.
+        */
        unsigned int current_level;
+
+       /**
+        * mali_dvfs_facility 是否被使能.
+        */
        bool enabled;
+
+       /**
+        * count_of_continuous_requests_to_jump_up_in_dvfs_level_table.
+        * 对 "连续" 的 requests_to_jump_up_in_dvfs_level_table 计数.
+        */
+       unsigned int m_count_of_requests_to_jump_up;
+
+       /**
+        * count_of_continuous_requests_to_jump_down_in_dvfs_level_table.
+        * 对 "连续" 的 requests_to_jump_down_in_dvfs_level_table 计数.
+        */
+       unsigned int m_count_of_requests_to_jump_down;
 };
 
 int mali_dvfs_init(struct device *dev);
+
 void mali_dvfs_term(struct device *dev);
-void mali_set_dvfs(struct device *dev, bool enable);
+
 bool mali_dvfs_is_enabled(struct device *dev);
+
 void mali_dvfs_enable(struct device *dev);
+
 void mali_dvfs_disable(struct device *dev);
+
 unsigned int mali_dvfs_utilisation(struct device *dev);
+
 int mali_dvfs_event(struct device *dev, u32 utilisation);
+
 #endif         /*_MALI_DVFS_H_*/