]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amdgpu/gfx11: Implement the GFX11 KGQ pipe reset
authorPrike Liang <Prike.Liang@amd.com>
Wed, 17 Jul 2024 06:58:00 +0000 (14:58 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 7 Apr 2025 19:18:58 +0000 (15:18 -0400)
Implement the kernel graphics queue pipe reset,and the driver
will fallback to pipe reset when the queue reset fails. However,
the ME FW hasn't fully supported pipe reset yet so disable the
KGQ pipe reset temporarily.

Signed-off-by: Prike Liang <Prike.Liang@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c

index 4eedd92f000be9b1b9da5cf4f209fc6d89303e11..06fe21e15ed61f6e1336e6cba9d1d98bf6a166a5 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "amdgpu_socbb.h"
 
+#define RS64_FW_UC_START_ADDR_LO 0x3000
+
 struct common_firmware_header {
        uint32_t size_bytes; /* size of the entire header+image(s) in bytes */
        uint32_t header_size_bytes; /* size of just the header in bytes */
index cedfcd1184301007b647b14fa895db3b002d9892..42a08751af5af69588f378419fa41c86f8160497 100644 (file)
@@ -6608,6 +6608,69 @@ static void gfx_v11_0_emit_mem_sync(struct amdgpu_ring *ring)
        amdgpu_ring_write(ring, gcr_cntl); /* GCR_CNTL */
 }
 
+static bool gfx_v11_pipe_reset_support(struct amdgpu_device *adev)
+{
+       /* Disable the pipe reset until the CPFW fully support it.*/
+       dev_warn_once(adev->dev, "The CPFW hasn't support pipe reset yet.\n");
+       return false;
+}
+
+
+static int gfx_v11_reset_gfx_pipe(struct amdgpu_ring *ring)
+{
+       struct amdgpu_device *adev = ring->adev;
+       uint32_t reset_pipe = 0, clean_pipe = 0;
+       int r;
+
+       if (!gfx_v11_pipe_reset_support(adev))
+               return -EOPNOTSUPP;
+
+       gfx_v11_0_set_safe_mode(adev, 0);
+       mutex_lock(&adev->srbm_mutex);
+       soc21_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
+
+       switch (ring->pipe) {
+       case 0:
+               reset_pipe = REG_SET_FIELD(reset_pipe, CP_ME_CNTL,
+                                          PFP_PIPE0_RESET, 1);
+               reset_pipe = REG_SET_FIELD(reset_pipe, CP_ME_CNTL,
+                                          ME_PIPE0_RESET, 1);
+               clean_pipe = REG_SET_FIELD(clean_pipe, CP_ME_CNTL,
+                                          PFP_PIPE0_RESET, 0);
+               clean_pipe = REG_SET_FIELD(clean_pipe, CP_ME_CNTL,
+                                          ME_PIPE0_RESET, 0);
+               break;
+       case 1:
+               reset_pipe = REG_SET_FIELD(reset_pipe, CP_ME_CNTL,
+                                          PFP_PIPE1_RESET, 1);
+               reset_pipe = REG_SET_FIELD(reset_pipe, CP_ME_CNTL,
+                                          ME_PIPE1_RESET, 1);
+               clean_pipe = REG_SET_FIELD(clean_pipe, CP_ME_CNTL,
+                                          PFP_PIPE1_RESET, 0);
+               clean_pipe = REG_SET_FIELD(clean_pipe, CP_ME_CNTL,
+                                          ME_PIPE1_RESET, 0);
+               break;
+       default:
+               break;
+       }
+
+       WREG32_SOC15(GC, 0, regCP_ME_CNTL, reset_pipe);
+       WREG32_SOC15(GC, 0, regCP_ME_CNTL, clean_pipe);
+
+       r = (RREG32(SOC15_REG_OFFSET(GC, 0, regCP_GFX_RS64_INSTR_PNTR1)) << 2) -
+                                               RS64_FW_UC_START_ADDR_LO;
+       soc21_grbm_select(adev, 0, 0, 0, 0);
+       mutex_unlock(&adev->srbm_mutex);
+       gfx_v11_0_unset_safe_mode(adev, 0);
+
+       dev_info(adev->dev, "The ring %s pipe reset to the ME firmware start PC: %s\n", ring->name,
+                       r == 0 ? "successfully" : "failed");
+       /* FIXME: Sometimes driver can't cache the ME firmware start PC correctly,
+        * so the pipe reset status relies on the later gfx ring test result.
+        */
+       return 0;
+}
+
 static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring, unsigned int vmid)
 {
        struct amdgpu_device *adev = ring->adev;
@@ -6617,8 +6680,13 @@ static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring, unsigned int vmid)
                return -EINVAL;
 
        r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, false);
-       if (r)
-               return r;
+       if (r) {
+
+               dev_warn(adev->dev, "reset via MES failed and try pipe reset %d\n", r);
+               r = gfx_v11_reset_gfx_pipe(ring);
+               if (r)
+                       return r;
+       }
 
        r = gfx_v11_0_kgq_init_queue(ring, true);
        if (r) {