diff options
author | Wayne Lin <Wayne.Lin@amd.com> | 2021-03-06 18:37:33 +0800 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2021-03-23 23:32:50 -0400 |
commit | cd95ef0097ca1c88c31aaa278d58a5ab45605e74 (patch) | |
tree | ba65d461f22c777412a1c59e5a0f9f27814f255f /drivers/gpu/drm | |
parent | 4870bd88136481f77c5b93da0423888870f3add5 (diff) | |
download | linux-cd95ef0097ca1c88c31aaa278d58a5ab45605e74.tar.bz2 |
drm/amd/display: Fix secure display lock problems
[Why]
Find out few locks problems while doing secure display. They are
following few parts:
1. crc_rd_work_lock in amdgpu_dm_crtc_handle_crc_window_irq() should
also use spin_lock_irqsave instead of spin_lock_irq.
2. In crc_win_update_set(), crc_rd_work_lock should be grabbed after
obtaining lock event_lock. Otherwise, will cause deadlock by conflicting
the lock order in amdgpu_dm_crtc_handle_crc_window_irq()
3. flush_work() in crc_win_update_set() is no need and will cause
deadlock since amdgpu_dm_crtc_notify_ta_to_read() also tries to grab
lock crc_rd_work_lock.
[How]
Fix above problems.
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
Reviewed-by: Solomon Chiu <Solomon.Chiu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 6 |
2 files changed, 7 insertions, 9 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c index 3adbaf50a558..c6d6baab106e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c @@ -433,7 +433,7 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc) struct amdgpu_device *adev = NULL; struct crc_rd_work *crc_rd_wrk = NULL; struct crc_params *crc_window = NULL, tmp_window; - unsigned long flags; + unsigned long flags1, flags2; struct crtc_position position; uint32_t v_blank; uint32_t v_back_porch; @@ -447,7 +447,7 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc) adev = drm_to_adev(crtc->dev); drm_dev = crtc->dev; - spin_lock_irqsave(&drm_dev->event_lock, flags); + spin_lock_irqsave(&drm_dev->event_lock, flags1); stream_state = acrtc->dm_irq_params.stream; cur_crc_src = acrtc->dm_irq_params.crc_src; timing_out = &stream_state->timing; @@ -508,10 +508,10 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc) if (acrtc->dm_irq_params.crc_window.skip_frame_cnt == 0) { if (adev->dm.crc_rd_wrk) { crc_rd_wrk = adev->dm.crc_rd_wrk; - spin_lock_irq(&crc_rd_wrk->crc_rd_work_lock); + spin_lock_irqsave(&crc_rd_wrk->crc_rd_work_lock, flags2); crc_rd_wrk->phy_inst = stream_state->link->link_enc_hw_inst; - spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock); + spin_unlock_irqrestore(&crc_rd_wrk->crc_rd_work_lock, flags2); schedule_work(&crc_rd_wrk->notify_ta_work); } } else { @@ -522,7 +522,7 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc) } cleanup: - spin_unlock_irqrestore(&drm_dev->event_lock, flags); + spin_unlock_irqrestore(&drm_dev->event_lock, flags1); } void amdgpu_dm_crtc_secure_display_resume(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 6d839d3fb6a3..b8644f49e0f2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -2695,14 +2695,12 @@ static int crc_win_update_set(void *data, u64 val) struct crc_rd_work *crc_rd_wrk = adev->dm.crc_rd_wrk; if (val) { - spin_lock_irq(&crc_rd_wrk->crc_rd_work_lock); spin_lock_irq(&adev_to_drm(adev)->event_lock); + spin_lock_irq(&crc_rd_wrk->crc_rd_work_lock); if (crc_rd_wrk && crc_rd_wrk->crtc) { old_crtc = crc_rd_wrk->crtc; old_acrtc = to_amdgpu_crtc(old_crtc); - flush_work(&adev->dm.crc_rd_wrk->notify_ta_work); } - new_acrtc = to_amdgpu_crtc(new_crtc); if (old_crtc && old_crtc != new_crtc) { @@ -2720,8 +2718,8 @@ static int crc_win_update_set(void *data, u64 val) new_acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0; crc_rd_wrk->crtc = new_crtc; } - spin_unlock_irq(&adev_to_drm(adev)->event_lock); spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock); + spin_unlock_irq(&adev_to_drm(adev)->event_lock); } return 0; |