summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c9
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c7
2 files changed, 14 insertions, 2 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f69a7e88546a..f4be2724471d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2239,6 +2239,8 @@ static int amdgpu_dm_early_fini(struct amdgpu_ip_block *ip_block)
static void amdgpu_dm_fini(struct amdgpu_device *adev)
{
int i;
+ struct drm_crtc *crtc;
+ struct amdgpu_crtc *acrtc;
if (adev->dm.vblank_control_workqueue) {
destroy_workqueue(adev->dm.vblank_control_workqueue);
@@ -2255,6 +2257,13 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
adev->dm.idle_workqueue = NULL;
}
+ /* Finalize ISM for each CRTC before dc_destroy() sets dm->dc to NULL */
+ drm_for_each_crtc(crtc, adev_to_drm(adev)) {
+ acrtc = to_amdgpu_crtc(crtc);
+ amdgpu_dm_ism_fini(&acrtc->ism);
+
+ }
+
amdgpu_dm_destroy_drm_device(&adev->dm);
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index 5d2715f78314..d69f5a75b685 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -457,9 +457,12 @@ static struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *cr
static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc)
{
- struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+ /*
+ * amdgpu_dm_ism_fini() is intentionally called in amdgpu_dm_fini().
+ * It must be called before dc_destroy() in amdgpu_dm_fini()
+ * to avoid ISM accessing an invalid dc handle once dc is released.
+ */
- amdgpu_dm_ism_fini(&acrtc->ism);
drm_crtc_cleanup(crtc);
kfree(crtc);
}