Set the s3/s0ix and s4 in the pm notifier so that we can skip the resource evictions in the pm notifier and pm prepare functions, then reset them in pm prepare so that they can be set properly in the suspend and freeze callbacks.
v2: always reset flags in pm prepare Cc: Mario Limonciello <mario.limoncie...@amd.com> Signed-off-by: Alex Deucher <alexander.deuc...@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 14 +++++++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 14 +++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 5ac7bd5942d01..a3e9f289e37c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4919,8 +4919,20 @@ static int amdgpu_device_pm_notifier(struct notifier_block *nb, unsigned long mo switch (mode) { case PM_HIBERNATION_PREPARE: adev->in_s4 = true; - fallthrough; + r = amdgpu_device_evict_resources(adev); + /* + * This is considered non-fatal at this time because + * amdgpu_device_prepare() will also fatally evict resources. + * See https://gitlab.freedesktop.org/drm/amd/-/issues/3781 + */ + if (r) + drm_warn(adev_to_drm(adev), "Failed to evict resources, freeze active processes if problems occur: %d\n", r); + break; case PM_SUSPEND_PREPARE: + if (amdgpu_acpi_is_s0ix_active(adev)) + adev->in_s0ix = true; + else if (amdgpu_acpi_is_s3_active(adev)) + adev->in_s3 = true; r = amdgpu_device_evict_resources(adev); /* * This is considered non-fatal at this time because diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 24ee4710f807f..60c032f124149 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -2516,22 +2516,29 @@ static int amdgpu_pmops_prepare(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(drm_dev); + int r; /* Return a positive number here so * DPM_FLAG_SMART_SUSPEND works properly */ if (amdgpu_device_supports_boco(drm_dev) && - pm_runtime_suspended(dev)) + pm_runtime_suspended(dev)) { + adev->in_s0ix = adev->in_s3 = adev->in_s4 = false; return 1; + } /* if we will not support s3 or s2i for the device * then skip suspend */ if (!amdgpu_acpi_is_s0ix_active(adev) && - !amdgpu_acpi_is_s3_active(adev)) + !amdgpu_acpi_is_s3_active(adev)) { + adev->in_s0ix = adev->in_s3 = adev->in_s4 = false; return 1; + } - return amdgpu_device_prepare(drm_dev); + r = amdgpu_device_prepare(drm_dev); + adev->in_s0ix = adev->in_s3 = adev->in_s4 = false; + return r; } static void amdgpu_pmops_complete(struct device *dev) @@ -2603,6 +2610,7 @@ static int amdgpu_pmops_freeze(struct device *dev) struct amdgpu_device *adev = drm_to_adev(drm_dev); int r; + adev->in_s4 = true; r = amdgpu_device_suspend(drm_dev, true); if (r) return r; -- 2.49.0