]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amdgpu: rework resume handling for display (v2)
authorAlex Deucher <alexander.deucher@amd.com>
Mon, 25 Nov 2024 18:59:09 +0000 (13:59 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 14 Dec 2024 19:04:15 +0000 (20:04 +0100)
commit 73dae652dcac776296890da215ee7dec357a1032 upstream.

Split resume into a 3rd step to handle displays when DCC is
enabled on DCN 4.0.1.  Move display after the buffer funcs
have been re-enabled so that the GPU will do the move and
properly set the DCC metadata for DCN.

v2: fix fence irq resume ordering

Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org # 6.11.x
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c

index 07f93f77de7dc2ca9d7b368c5e15f1c90b8619de..51904906545e5975de775ce3dafee6a3df4a3397 100644 (file)
@@ -3666,7 +3666,7 @@ static int amdgpu_device_ip_resume_phase1(struct amdgpu_device *adev)
  *
  * @adev: amdgpu_device pointer
  *
- * First resume function for hardware IPs.  The list of all the hardware
+ * Second resume function for hardware IPs.  The list of all the hardware
  * IPs that make up the asic is walked and the resume callbacks are run for
  * all blocks except COMMON, GMC, and IH.  resume puts the hardware into a
  * functional state after a suspend and updates the software state as
@@ -3684,6 +3684,7 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev)
                if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
                    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
                    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH ||
+                   adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE ||
                    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)
                        continue;
                r = adev->ip_blocks[i].version->funcs->resume(adev);
@@ -3698,6 +3699,36 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev)
        return 0;
 }
 
+/**
+ * amdgpu_device_ip_resume_phase3 - run resume for hardware IPs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Third resume function for hardware IPs.  The list of all the hardware
+ * IPs that make up the asic is walked and the resume callbacks are run for
+ * all DCE.  resume puts the hardware into a functional state after a suspend
+ * and updates the software state as necessary.  This function is also used
+ * for restoring the GPU after a GPU reset.
+ *
+ * Returns 0 on success, negative error code on failure.
+ */
+static int amdgpu_device_ip_resume_phase3(struct amdgpu_device *adev)
+{
+       int i, r;
+
+       for (i = 0; i < adev->num_ip_blocks; i++) {
+               if (!adev->ip_blocks[i].status.valid || adev->ip_blocks[i].status.hw)
+                       continue;
+               if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) {
+                       r = adev->ip_blocks[i].version->funcs->resume(adev);
+                       if (r)
+                               return r;
+               }
+       }
+
+       return 0;
+}
+
 /**
  * amdgpu_device_ip_resume - run resume for hardware IPs
  *
@@ -3727,6 +3758,13 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev)
        if (adev->mman.buffer_funcs_ring->sched.ready)
                amdgpu_ttm_set_buffer_funcs_status(adev, true);
 
+       if (r)
+               return r;
+
+       amdgpu_fence_driver_hw_init(adev);
+
+       r = amdgpu_device_ip_resume_phase3(adev);
+
        return r;
 }
 
@@ -4809,7 +4847,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
                dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r);
                goto exit;
        }
-       amdgpu_fence_driver_hw_init(adev);
 
        if (!adev->in_s0ix) {
                r = amdgpu_amdkfd_resume(adev, adev->in_runpm);
@@ -5431,6 +5468,10 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle,
                                if (tmp_adev->mman.buffer_funcs_ring->sched.ready)
                                        amdgpu_ttm_set_buffer_funcs_status(tmp_adev, true);
 
+                               r = amdgpu_device_ip_resume_phase3(tmp_adev);
+                               if (r)
+                                       goto out;
+
                                if (vram_lost)
                                        amdgpu_device_fill_reset_magic(tmp_adev);