summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
diff options
context:
space:
mode:
authorEvan Quan <evan.quan@amd.com>2022-01-25 11:09:00 +0300
committerAlex Deucher <alexander.deucher@amd.com>2022-01-27 23:48:22 +0300
commit75513bf5d72cd1a81401866642f4a8052b2d4420 (patch)
tree333d67380200cc370548fd401a02ebf199bfa887 /drivers/gpu/drm/amd/pm/amdgpu_dpm.c
parentf4e2a66dae996b4fa2cc21b1904798ad1dc83049 (diff)
downloadlinux-75513bf5d72cd1a81401866642f4a8052b2d4420.tar.xz
drm/amd/pm: fix the deadlock observed on performance_level setting
The sub-routine(amdgpu_gfx_off_ctrl) tried to obtain the lock adev->pm.mutex which was actually hold by amdgpu_dpm_force_performance_level. A deadlock happened then. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/pm/amdgpu_dpm.c')
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_dpm.c50
1 files changed, 17 insertions, 33 deletions
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
index 5fc33893a68c..ef574c96b41c 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
@@ -692,25 +692,16 @@ void amdgpu_dpm_set_power_state(struct amdgpu_device *adev,
amdgpu_dpm_compute_clocks(adev);
}
-static enum amd_dpm_forced_level amdgpu_dpm_get_performance_level_locked(struct amdgpu_device *adev)
+enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev)
{
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
enum amd_dpm_forced_level level;
+ mutex_lock(&adev->pm.mutex);
if (pp_funcs->get_performance_level)
level = pp_funcs->get_performance_level(adev->powerplay.pp_handle);
else
level = adev->pm.dpm.forced_level;
-
- return level;
-}
-
-enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev)
-{
- enum amd_dpm_forced_level level;
-
- mutex_lock(&adev->pm.mutex);
- level = amdgpu_dpm_get_performance_level_locked(adev);
mutex_unlock(&adev->pm.mutex);
return level;
@@ -725,23 +716,16 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev,
AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
- int ret = 0;
if (!pp_funcs->force_performance_level)
return 0;
- mutex_lock(&adev->pm.mutex);
-
- if (adev->pm.dpm.thermal_active) {
- ret = -EINVAL;
- goto out;
- }
+ if (adev->pm.dpm.thermal_active)
+ return -EINVAL;
- current_level = amdgpu_dpm_get_performance_level_locked(adev);
- if (current_level == level) {
- ret = 0;
- goto out;
- }
+ current_level = amdgpu_dpm_get_performance_level(adev);
+ if (current_level == level)
+ return 0;
if (adev->asic_type == CHIP_RAVEN) {
if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) {
@@ -755,10 +739,8 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev,
}
if (!(current_level & profile_mode_mask) &&
- (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) {
- ret = -EINVAL;
- goto out;
- }
+ (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT))
+ return -EINVAL;
if (!(current_level & profile_mode_mask) &&
(level & profile_mode_mask)) {
@@ -780,17 +762,19 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev,
AMD_PG_STATE_GATE);
}
+ mutex_lock(&adev->pm.mutex);
+
if (pp_funcs->force_performance_level(adev->powerplay.pp_handle,
- level))
- ret = -EINVAL;
+ level)) {
+ mutex_unlock(&adev->pm.mutex);
+ return -EINVAL;
+ }
- if (!ret)
- adev->pm.dpm.forced_level = level;
+ adev->pm.dpm.forced_level = level;
-out:
mutex_unlock(&adev->pm.mutex);
- return ret;
+ return 0;
}
int amdgpu_dpm_get_pp_num_states(struct amdgpu_device *adev,