]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd: Add support for a complete pmops action
authorMario Limonciello <mario.limonciello@amd.com>
Mon, 2 Jun 2025 01:44:30 +0000 (20:44 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 18 Jun 2025 16:19:18 +0000 (12:19 -0400)
complete() callbacks are supposed to handle reversing anything
that occurred during prepare() callbacks.  They'll be called on every
power state transition, and will also be called if the sequence is
failed (such as an aborted suspend).

Add support for IP blocks to support this action.

Reviewed-by: Alex Hung <alex.hung@amd.com>
Link: https://lore.kernel.org/r/20250602014432.3538345-2-superm1@kernel.org
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/include/amd_shared.h

index 09f45ff40057147894c3161f160b0c425127f4ea..5e2f086d2c99e7db41245fb3306af0b8a428e05b 100644 (file)
@@ -1620,6 +1620,7 @@ void amdgpu_driver_release_kms(struct drm_device *dev);
 
 int amdgpu_device_ip_suspend(struct amdgpu_device *adev);
 int amdgpu_device_prepare(struct drm_device *dev);
+void amdgpu_device_complete(struct drm_device *dev);
 int amdgpu_device_suspend(struct drm_device *dev, bool fbcon);
 int amdgpu_device_resume(struct drm_device *dev, bool fbcon);
 u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc);
index b16f7c4beb22b9fd77fce0f7d1862fcb9b2f884b..d9b1bd97491fcc053a952ee17592c3ae3122723a 100644 (file)
@@ -5040,6 +5040,28 @@ int amdgpu_device_prepare(struct drm_device *dev)
        return 0;
 }
 
+/**
+ * amdgpu_device_complete - complete power state transition
+ *
+ * @dev: drm dev pointer
+ *
+ * Undo the changes from amdgpu_device_prepare. This will be
+ * called on all resume transitions, including those that failed.
+ */
+void amdgpu_device_complete(struct drm_device *dev)
+{
+       struct amdgpu_device *adev = drm_to_adev(dev);
+       int i;
+
+       for (i = 0; i < adev->num_ip_blocks; i++) {
+               if (!adev->ip_blocks[i].status.valid)
+                       continue;
+               if (!adev->ip_blocks[i].version->funcs->complete)
+                       continue;
+               adev->ip_blocks[i].version->funcs->complete(&adev->ip_blocks[i]);
+       }
+}
+
 /**
  * amdgpu_device_suspend - initiate device suspend
  *
index efd6bff95e4e1756a69e1d2b1c85e4db6a3ea209..7f8fa69300bf447cbfcfc148c81d26ab61e827d7 100644 (file)
@@ -2576,7 +2576,7 @@ static int amdgpu_pmops_prepare(struct device *dev)
 
 static void amdgpu_pmops_complete(struct device *dev)
 {
-       /* nothing to do */
+       amdgpu_device_complete(dev_get_drvdata(dev));
 }
 
 static int amdgpu_pmops_suspend(struct device *dev)
index 11374a2cbab87eb06329b573cbf7e0bfe8a76389..a06e92b1b2ef9f4c1fbd61236ec93c2e0624b2f3 100644 (file)
@@ -427,6 +427,7 @@ struct amd_ip_funcs {
        int (*prepare_suspend)(struct amdgpu_ip_block *ip_block);
        int (*suspend)(struct amdgpu_ip_block *ip_block);
        int (*resume)(struct amdgpu_ip_block *ip_block);
+       void (*complete)(struct amdgpu_ip_block *ip_block);
        bool (*is_idle)(struct amdgpu_ip_block *ip_block);
        int (*wait_for_idle)(struct amdgpu_ip_block *ip_block);
        bool (*check_soft_reset)(struct amdgpu_ip_block *ip_block);