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