Use it to call disply code dependent on device->drv_data
before it's set to NULL on device unplug

Signed-off-by: Andrey Grodzovsky <andrey.grodzov...@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c        | 20 ++++++++++++++++++++
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 ++++++++++--
 drivers/gpu/drm/amd/include/amd_shared.h          |  2 ++
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 797d94d..96368a8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -2508,6 +2508,24 @@ static int amdgpu_device_ip_late_init(struct 
amdgpu_device *adev)
        return 0;
 }
 
+static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
+{
+       int i, r;
+
+       for (i = 0; i < adev->num_ip_blocks; i++) {
+               if (!adev->ip_blocks[i].version->funcs->early_fini)
+                       continue;
+
+               r = adev->ip_blocks[i].version->funcs->early_fini((void *)adev);
+               if (r) {
+                       DRM_DEBUG("early_fini of IP block <%s> failed %d\n",
+                                 adev->ip_blocks[i].version->funcs->name, r);
+               }
+       }
+
+       return 0;
+}
+
 /**
  * amdgpu_device_ip_fini - run fini for hardware IPs
  *
@@ -3585,6 +3603,8 @@ void amdgpu_device_fini_early(struct amdgpu_device *adev)
        amdgpu_fbdev_fini(adev);
 
        amdgpu_irq_fini_early(adev);
+
+       amdgpu_device_ip_fini_early(adev);
 }
 
 void amdgpu_device_fini_late(struct amdgpu_device *adev)
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 1da4ad5..278d1f6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1158,6 +1158,15 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        return -EINVAL;
 }
 
+static int amdgpu_dm_early_fini(void *handle)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       amdgpu_dm_audio_fini(adev);
+
+       return 0;
+}
+
 static void amdgpu_dm_fini(struct amdgpu_device *adev)
 {
        int i;
@@ -1166,8 +1175,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
                drm_encoder_cleanup(&adev->dm.mst_encoders[i].base);
        }
 
-       amdgpu_dm_audio_fini(adev);
-
        amdgpu_dm_destroy_drm_device(&adev->dm);
 
 #ifdef CONFIG_DRM_AMD_DC_HDCP
@@ -2150,6 +2157,7 @@ static const struct amd_ip_funcs amdgpu_dm_funcs = {
        .late_init = dm_late_init,
        .sw_init = dm_sw_init,
        .sw_fini = dm_sw_fini,
+       .early_fini = amdgpu_dm_early_fini,
        .hw_init = dm_hw_init,
        .hw_fini = dm_hw_fini,
        .suspend = dm_suspend,
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h 
b/drivers/gpu/drm/amd/include/amd_shared.h
index 9676016..63bb846 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -239,6 +239,7 @@ enum amd_dpm_forced_level;
  * @late_init: sets up late driver/hw state (post hw_init) - Optional
  * @sw_init: sets up driver state, does not configure hw
  * @sw_fini: tears down driver state, does not configure hw
+ * @early_fini: tears down stuff before dev detached from driver
  * @hw_init: sets up the hw state
  * @hw_fini: tears down the hw state
  * @late_fini: final cleanup
@@ -267,6 +268,7 @@ struct amd_ip_funcs {
        int (*late_init)(void *handle);
        int (*sw_init)(void *handle);
        int (*sw_fini)(void *handle);
+       int (*early_fini)(void *handle);
        int (*hw_init)(void *handle);
        int (*hw_fini)(void *handle);
        void (*late_fini)(void *handle);
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to