Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Lijo Lazar and committed by
Alex Deucher
58893392 178ad3a9

+35 -23
+35 -23
drivers/gpu/drm/amd/pm/amdgpu_dpm.c
··· 987 987 return level; 988 988 } 989 989 990 + static void amdgpu_dpm_enter_umd_state(struct amdgpu_device *adev) 991 + { 992 + /* enter UMD Pstate */ 993 + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_GFX, 994 + AMD_PG_STATE_UNGATE); 995 + amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_GFX, 996 + AMD_CG_STATE_UNGATE); 997 + } 998 + 999 + static void amdgpu_dpm_exit_umd_state(struct amdgpu_device *adev) 1000 + { 1001 + /* exit UMD Pstate */ 1002 + amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_GFX, 1003 + AMD_CG_STATE_GATE); 1004 + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_GFX, 1005 + AMD_PG_STATE_GATE); 1006 + } 1007 + 990 1008 int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, 991 1009 enum amd_dpm_forced_level level) 992 1010 { ··· 1025 1007 if (current_level == level) 1026 1008 return 0; 1027 1009 1010 + if (!(current_level & profile_mode_mask) && 1011 + (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) 1012 + return -EINVAL; 1013 + 1028 1014 if (adev->asic_type == CHIP_RAVEN) { 1029 1015 if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) { 1030 1016 if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && ··· 1040 1018 } 1041 1019 } 1042 1020 1043 - if (!(current_level & profile_mode_mask) && 1044 - (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) 1045 - return -EINVAL; 1046 - 1047 - if (!(current_level & profile_mode_mask) && 1048 - (level & profile_mode_mask)) { 1049 - /* enter UMD Pstate */ 1050 - amdgpu_device_ip_set_powergating_state(adev, 1051 - AMD_IP_BLOCK_TYPE_GFX, 1052 - AMD_PG_STATE_UNGATE); 1053 - amdgpu_device_ip_set_clockgating_state(adev, 1054 - AMD_IP_BLOCK_TYPE_GFX, 1055 - AMD_CG_STATE_UNGATE); 1056 - } else if ((current_level & profile_mode_mask) && 1057 - !(level & profile_mode_mask)) { 1058 - /* exit UMD Pstate */ 1059 - amdgpu_device_ip_set_clockgating_state(adev, 1060 - AMD_IP_BLOCK_TYPE_GFX, 1061 - AMD_CG_STATE_GATE); 1062 - amdgpu_device_ip_set_powergating_state(adev, 1063 - AMD_IP_BLOCK_TYPE_GFX, 1064 - AMD_PG_STATE_GATE); 1065 - } 1021 + if (!(current_level & profile_mode_mask) && (level & profile_mode_mask)) 1022 + amdgpu_dpm_enter_umd_state(adev); 1023 + else if ((current_level & profile_mode_mask) && 1024 + !(level & profile_mode_mask)) 1025 + amdgpu_dpm_exit_umd_state(adev); 1066 1026 1067 1027 mutex_lock(&adev->pm.mutex); 1068 1028 1069 1029 if (pp_funcs->force_performance_level(adev->powerplay.pp_handle, 1070 1030 level)) { 1071 1031 mutex_unlock(&adev->pm.mutex); 1032 + /* If new level failed, retain the umd state as before */ 1033 + if (!(current_level & profile_mode_mask) && 1034 + (level & profile_mode_mask)) 1035 + amdgpu_dpm_exit_umd_state(adev); 1036 + else if ((current_level & profile_mode_mask) && 1037 + !(level & profile_mode_mask)) 1038 + amdgpu_dpm_enter_umd_state(adev); 1039 + 1072 1040 return -EINVAL; 1073 1041 } 1074 1042