amdgpu_vkms_suspend()/resume() are IP block callbacks shared by system
suspend/resume and GPU recovery. Calling drm_mode_config_helper_suspend()
and drm_mode_config_helper_resume() from them makes GPU recovery take
clientlist_mutex and the modeset locks and duplicate the atomic state
while holding reset_domain->sem. Lockdep reports:

  Chain exists of:
    &dev->clientlist_mutex --> &userq_mgr->userq_mutex --> &reset_domain->sem

VKMS has no hardware state that a reset can lose, so the reset path never
needs these helpers. Call them from amdgpu_device_suspend()/resume()
instead and leave the IP callbacks with only the hardware init.

Signed-off-by: Prike Liang <[email protected]>
Cc: Sun peng Li (Leo) <[email protected]>
Cc: Mario Limonciello <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 19 ++++++++++++++++++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c   | 14 +-------------
 2 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 3ced5c18daaa..65c60b47189f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -4570,9 +4570,16 @@ int amdgpu_device_suspend(struct drm_device *dev, bool 
notify_clients)
 
        amdgpu_ras_suspend(adev);
 
+       /* VKMS modeset state is saved here, never from the reset path */
+       if (adev->enable_virtual_display) {
+               r = drm_mode_config_helper_suspend(dev);
+               if (r)
+                       goto unwind_smartshift;
+       }
+
        r = amdgpu_device_ip_suspend_phase1(adev);
        if (r)
-               goto unwind_smartshift;
+               goto unwind_vkms;
 
        amdgpu_amdkfd_suspend(adev, !amdgpu_sriov_vf(adev) && !adev->in_runpm);
        r = amdgpu_userq_suspend(adev);
@@ -4620,6 +4627,10 @@ int amdgpu_device_suspend(struct drm_device *dev, bool 
notify_clients)
                return r;
        }
 
+unwind_vkms:
+       if (adev->enable_virtual_display)
+               drm_mode_config_helper_resume(dev);
+
 unwind_smartshift:
        rec = amdgpu_acpi_smart_shift_update(adev, AMDGPU_SS_DEV_D0);
        if (rec) {
@@ -4719,6 +4730,12 @@ int amdgpu_device_resume(struct drm_device *dev, bool 
notify_clients)
                goto exit;
        }
 
+       if (adev->enable_virtual_display) {
+               r = drm_mode_config_helper_resume(dev);
+               if (r)
+                       goto exit;
+       }
+
        r = amdgpu_amdkfd_resume(adev, !amdgpu_sriov_vf(adev) && 
!adev->in_runpm);
        if (r)
                goto exit;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
index d6b51b3f216b..6de33f14d909 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -488,24 +488,12 @@ static int amdgpu_vkms_hw_fini(struct amdgpu_ip_block 
*ip_block)
 
 static int amdgpu_vkms_suspend(struct amdgpu_ip_block *ip_block)
 {
-       struct amdgpu_device *adev = ip_block->adev;
-       int r;
-
-       r = drm_mode_config_helper_suspend(adev_to_drm(adev));
-       if (r)
-               return r;
-
        return 0;
 }
 
 static int amdgpu_vkms_resume(struct amdgpu_ip_block *ip_block)
 {
-       int r;
-
-       r = amdgpu_vkms_hw_init(ip_block);
-       if (r)
-               return r;
-       return drm_mode_config_helper_resume(adev_to_drm(ip_block->adev));
+       return amdgpu_vkms_hw_init(ip_block);
 }
 
 static int amdgpu_vkms_set_clockgating_state(struct amdgpu_ip_block *ip_block,
-- 
2.34.1

Reply via email to