]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/display: Fix secure display lock problems
authorWayne Lin <Wayne.Lin@amd.com>
Sat, 6 Mar 2021 10:37:33 +0000 (18:37 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 24 Mar 2021 03:32:50 +0000 (23:32 -0400)
[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>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c

index 3adbaf50a5588e4eff258bde87fbd702530df317..c6d6baab106ed1205061544997c640437f1eda12 100644 (file)
@@ -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)
index 6d839d3fb6a3bcf594ca4e66b785932043f0ca41..b8644f49e0f21c6c3f0b3929894e21c0dd7a0360 100644 (file)
@@ -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;