From: chenzhen Date: Wed, 28 Oct 2015 08:45:04 +0000 (+0800) Subject: rk312x, mali_400: make it more 'difficult' to dump down in mali_dvfs_list. X-Git-Tag: firefly_0821_release~3664 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=1804151a2ef6eb224d6ff23ef9d4ef5053cbf19a;p=firefly-linux-kernel-4.4.55.git rk312x, mali_400: make it more 'difficult' to dump down in mali_dvfs_list. Change-Id: If5fd646aa6ca7f7383db70c84ff71f1570fe23b1 Signed-off-by: chenzhen --- diff --git a/drivers/gpu/arm/mali400/mali/platform/rk30/mali_dvfs.c b/drivers/gpu/arm/mali400/mali/platform/rk30/mali_dvfs.c old mode 100755 new mode 100644 index 26ca41cba127..a3d8de0f1b66 --- a/drivers/gpu/arm/mali400/mali/platform/rk30/mali_dvfs.c +++ b/drivers/gpu/arm/mali400/mali/platform/rk30/mali_dvfs.c @@ -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 @@ -23,30 +40,111 @@ #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); } + diff --git a/drivers/gpu/arm/mali400/mali/platform/rk30/mali_dvfs.h b/drivers/gpu/arm/mali400/mali/platform/rk30/mali_dvfs.h old mode 100755 new mode 100644 index ddb68d99ca35..bbf837f7afa9 --- a/drivers/gpu/arm/mali400/mali/platform/rk30/mali_dvfs.h +++ b/drivers/gpu/arm/mali400/mali/platform/rk30/mali_dvfs.h @@ -12,19 +12,55 @@ #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_*/