mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-02-20 09:31:21 -05:00
drm/amd/pm: Revert state if force level fails
Before forcing level, CG/PG is disabled or enabled depending on the new level. However if the force level operation fails, CG/PG state remains modified. Revert the state change on failure. Also, move invalid operation checks to the beginning before any logic that could change SOC state. Signed-off-by: Lijo Lazar <lijo.lazar@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
@@ -987,6 +987,24 @@ enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device
|
||||
return level;
|
||||
}
|
||||
|
||||
static void amdgpu_dpm_enter_umd_state(struct amdgpu_device *adev)
|
||||
{
|
||||
/* enter UMD Pstate */
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_GFX,
|
||||
AMD_PG_STATE_UNGATE);
|
||||
amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_GFX,
|
||||
AMD_CG_STATE_UNGATE);
|
||||
}
|
||||
|
||||
static void amdgpu_dpm_exit_umd_state(struct amdgpu_device *adev)
|
||||
{
|
||||
/* exit UMD Pstate */
|
||||
amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_GFX,
|
||||
AMD_CG_STATE_GATE);
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_GFX,
|
||||
AMD_PG_STATE_GATE);
|
||||
}
|
||||
|
||||
int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev,
|
||||
enum amd_dpm_forced_level level)
|
||||
{
|
||||
@@ -1007,6 +1025,10 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev,
|
||||
if (current_level == level)
|
||||
return 0;
|
||||
|
||||
if (!(current_level & profile_mode_mask) &&
|
||||
(level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT))
|
||||
return -EINVAL;
|
||||
|
||||
if (adev->asic_type == CHIP_RAVEN) {
|
||||
if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) {
|
||||
if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
|
||||
@@ -1018,35 +1040,25 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev,
|
||||
}
|
||||
}
|
||||
|
||||
if (!(current_level & profile_mode_mask) &&
|
||||
(level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT))
|
||||
return -EINVAL;
|
||||
|
||||
if (!(current_level & profile_mode_mask) &&
|
||||
(level & profile_mode_mask)) {
|
||||
/* enter UMD Pstate */
|
||||
amdgpu_device_ip_set_powergating_state(adev,
|
||||
AMD_IP_BLOCK_TYPE_GFX,
|
||||
AMD_PG_STATE_UNGATE);
|
||||
amdgpu_device_ip_set_clockgating_state(adev,
|
||||
AMD_IP_BLOCK_TYPE_GFX,
|
||||
AMD_CG_STATE_UNGATE);
|
||||
} else if ((current_level & profile_mode_mask) &&
|
||||
!(level & profile_mode_mask)) {
|
||||
/* exit UMD Pstate */
|
||||
amdgpu_device_ip_set_clockgating_state(adev,
|
||||
AMD_IP_BLOCK_TYPE_GFX,
|
||||
AMD_CG_STATE_GATE);
|
||||
amdgpu_device_ip_set_powergating_state(adev,
|
||||
AMD_IP_BLOCK_TYPE_GFX,
|
||||
AMD_PG_STATE_GATE);
|
||||
}
|
||||
if (!(current_level & profile_mode_mask) && (level & profile_mode_mask))
|
||||
amdgpu_dpm_enter_umd_state(adev);
|
||||
else if ((current_level & profile_mode_mask) &&
|
||||
!(level & profile_mode_mask))
|
||||
amdgpu_dpm_exit_umd_state(adev);
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
|
||||
if (pp_funcs->force_performance_level(adev->powerplay.pp_handle,
|
||||
level)) {
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
/* If new level failed, retain the umd state as before */
|
||||
if (!(current_level & profile_mode_mask) &&
|
||||
(level & profile_mode_mask))
|
||||
amdgpu_dpm_exit_umd_state(adev);
|
||||
else if ((current_level & profile_mode_mask) &&
|
||||
!(level & profile_mode_mask))
|
||||
amdgpu_dpm_enter_umd_state(adev);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user