From 93ea54946564a0da7b7ba0b2b8ac24404e812aa0 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 29 Aug 2017 16:08:56 +0800 Subject: [PATCH 0908/4131] drm/amd/powerplay: add UMD P-state in powerplay. This feature is for UMD to run benchmark in a power state that is as steady as possible. kmd need to fix the power state as stable as possible. now, kmd support four level: profile_standard,peak,min_sclk,min_mclk move common related code to amd_powerplay.c Change-Id: I0cd72bac4c98028ab644e68d02c0adee6dd220a6 Reviewed-by: Alex Deucher Signed-off-by: Rex Zhu --- drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 47 +++++++++++++++++- drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c | 36 -------------- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 58 ++++------------------ drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 53 +++----------------- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 4 +- 5 files changed, 66 insertions(+), 132 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 94bed3c..75c810f 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -30,7 +30,6 @@ #include "pp_instance.h" #include "power_state.h" - static inline int pp_check(struct pp_instance *handle) { if (handle == NULL || handle->pp_valid != PP_VALID) @@ -287,6 +286,42 @@ static int pp_dpm_fw_loading_complete(void *handle) return 0; } +static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr, + enum amd_dpm_forced_level *level) +{ + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + + if (!(hwmgr->dpm_level & profile_mode_mask)) { + /* enter umd pstate, save current level, disable gfx cg*/ + if (*level & profile_mode_mask) { + hwmgr->saved_dpm_level = hwmgr->dpm_level; + hwmgr->en_umd_pstate = true; + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_UNGATE); + cgs_set_powergating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_UNGATE); + } + } else { + /* exit umd pstate, restore level, enable gfx cg*/ + if (!(*level & profile_mode_mask)) { + if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) + *level = hwmgr->saved_dpm_level; + hwmgr->en_umd_pstate = false; + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_GATE); + cgs_set_powergating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_GATE); + } + } +} + static int pp_dpm_force_performance_level(void *handle, enum amd_dpm_forced_level level) { @@ -301,14 +336,22 @@ static int pp_dpm_force_performance_level(void *handle, hwmgr = pp_handle->hwmgr; + if (level == hwmgr->dpm_level) + return 0; + if (hwmgr->hwmgr_func->force_dpm_level == NULL) { pr_info("%s was not implemented.\n", __func__); return 0; } mutex_lock(&pp_handle->pp_lock); + pp_dpm_en_umd_pstate(hwmgr, &level); + hwmgr->request_dpm_level = level; hwmgr_handle_task(pp_handle, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL); - hwmgr->hwmgr_func->force_dpm_level(hwmgr, level); + ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level); + if (!ret) + hwmgr->dpm_level = hwmgr->request_dpm_level; + mutex_unlock(&pp_handle->pp_lock); return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index b9c61ec..a301003 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -1314,57 +1314,21 @@ static int cz_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level) { int ret = 0; - uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; - - if (level == hwmgr->dpm_level) - return ret; - - if (!(hwmgr->dpm_level & profile_mode_mask)) { - /* enter profile mode, save current level, disable gfx cg*/ - if (level & profile_mode_mask) { - hwmgr->saved_dpm_level = hwmgr->dpm_level; - cgs_set_clockgating_state(hwmgr->device, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); - } - } else { - /* exit profile mode, restore level, enable gfx cg*/ - if (!(level & profile_mode_mask)) { - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) - level = hwmgr->saved_dpm_level; - cgs_set_clockgating_state(hwmgr->device, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - } - } switch (level) { case AMD_DPM_FORCED_LEVEL_HIGH: case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: ret = cz_phm_force_dpm_highest(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_LOW: case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: ret = cz_phm_force_dpm_lowest(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_AUTO: ret = cz_phm_unforce_dpm_levels(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_MANUAL: - hwmgr->dpm_level = level; - break; case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: default: break; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 5d5a813..812c67f 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -2568,51 +2568,16 @@ static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr, uint32_t sclk_mask = 0; uint32_t mclk_mask = 0; uint32_t pcie_mask = 0; - uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; - - if (level == hwmgr->dpm_level) - return ret; - - if (!(hwmgr->dpm_level & profile_mode_mask)) { - /* enter profile mode, save current level, disable gfx cg*/ - if (level & profile_mode_mask) { - hwmgr->saved_dpm_level = hwmgr->dpm_level; - cgs_set_clockgating_state(hwmgr->device, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); - } - } else { - /* exit profile mode, restore level, enable gfx cg*/ - if (!(level & profile_mode_mask)) { - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) - level = hwmgr->saved_dpm_level; - cgs_set_clockgating_state(hwmgr->device, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - } - } switch (level) { case AMD_DPM_FORCED_LEVEL_HIGH: ret = smu7_force_dpm_highest(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_LOW: ret = smu7_force_dpm_lowest(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_AUTO: ret = smu7_unforce_dpm_levels(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: @@ -2621,26 +2586,23 @@ static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr, ret = smu7_get_profiling_clk(hwmgr, level, &sclk_mask, &mclk_mask, &pcie_mask); if (ret) return ret; - hwmgr->dpm_level = level; smu7_force_clock_level(hwmgr, PP_SCLK, 1<dpm_level = level; - break; case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: default: break; } - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->saved_dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); - else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->saved_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr); - - return 0; + if (!ret) { + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); + else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr); + } + return ret; } static int smu7_get_power_state_size(struct pp_hwmgr *hwmgr) @@ -4248,9 +4210,9 @@ static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - if (hwmgr->dpm_level & (AMD_DPM_FORCED_LEVEL_AUTO | - AMD_DPM_FORCED_LEVEL_LOW | - AMD_DPM_FORCED_LEVEL_HIGH)) + if (hwmgr->request_dpm_level & (AMD_DPM_FORCED_LEVEL_AUTO | + AMD_DPM_FORCED_LEVEL_LOW | + AMD_DPM_FORCED_LEVEL_HIGH)) return -EINVAL; switch (type) { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index ca232a9..0f7fbb5 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -4309,51 +4309,16 @@ static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, uint32_t sclk_mask = 0; uint32_t mclk_mask = 0; uint32_t soc_mask = 0; - uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; - - if (level == hwmgr->dpm_level) - return ret; - - if (!(hwmgr->dpm_level & profile_mode_mask)) { - /* enter profile mode, save current level, disable gfx cg*/ - if (level & profile_mode_mask) { - hwmgr->saved_dpm_level = hwmgr->dpm_level; - cgs_set_clockgating_state(hwmgr->device, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); - } - } else { - /* exit profile mode, restore level, enable gfx cg*/ - if (!(level & profile_mode_mask)) { - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) - level = hwmgr->saved_dpm_level; - cgs_set_clockgating_state(hwmgr->device, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - } - } switch (level) { case AMD_DPM_FORCED_LEVEL_HIGH: ret = vega10_force_dpm_highest(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_LOW: ret = vega10_force_dpm_lowest(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_AUTO: ret = vega10_unforce_dpm_levels(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: @@ -4362,24 +4327,22 @@ static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, ret = vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); if (ret) return ret; - hwmgr->dpm_level = level; vega10_force_clock_level(hwmgr, PP_SCLK, 1<dpm_level = level; - break; case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: default: break; } - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->saved_dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_NONE); - else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->saved_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_AUTO); - - return 0; + if (!ret) { + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_NONE); + else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_AUTO); + } + return ret; } static int vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr) @@ -4627,7 +4590,7 @@ static int vega10_force_clock_level(struct pp_hwmgr *hwmgr, struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); int i; - if (hwmgr->dpm_level & (AMD_DPM_FORCED_LEVEL_AUTO | + if (hwmgr->request_dpm_level & (AMD_DPM_FORCED_LEVEL_AUTO | AMD_DPM_FORCED_LEVEL_LOW | AMD_DPM_FORCED_LEVEL_HIGH)) return -EINVAL; diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index c649354..3bbe7d5 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -747,6 +747,7 @@ struct pp_hwmgr { enum amd_dpm_forced_level dpm_level; enum amd_dpm_forced_level saved_dpm_level; + enum amd_dpm_forced_level request_dpm_level; bool block_hw_access; struct phm_gfx_arbiter gfx_arbiter; struct phm_acp_arbiter acp_arbiter; @@ -786,12 +787,13 @@ struct pp_hwmgr { struct amd_pp_display_configuration display_config; uint32_t feature_mask; - /* power profile */ + /* UMD Pstate */ struct amd_pp_profile gfx_power_profile; struct amd_pp_profile compute_power_profile; struct amd_pp_profile default_gfx_power_profile; struct amd_pp_profile default_compute_power_profile; enum amd_pp_profile_type current_power_profile; + bool en_umd_pstate; }; extern int hwmgr_early_init(struct pp_instance *handle); -- 2.7.4