Split amdgpu_gfx_mes_reset_queue_start() into reset+unmap now and queue
reinit later, and do the remap only after amdgpu_mes_resume(). Avoids
re-adding legacy queues while MES gangs are still suspended.

Suggested-by: Shaoyun Liu <[email protected]>
Signed-off-by: Jesse Zhang <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 70 +++++++++++++++++++------
 drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h |  1 +
 2 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index 982b41606d48..a5b835d0c166 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -1989,10 +1989,24 @@ static ssize_t amdgpu_gfx_get_compute_reset_mask(struct 
device *dev,
        return amdgpu_show_reset_mask(buf, adev->gfx.compute_supported_reset);
 }
 
+static int amdgpu_gfx_mes_reset_queue_reinit(struct amdgpu_ring *ring)
+{
+       struct amdgpu_device *adev = ring->adev;
+       int r;
+
+       amdgpu_gfx_mqd_reset_restore(ring);
+
+       r = amdgpu_mes_map_legacy_queue(adev, ring, 0);
+       if (r)
+               dev_err(adev->dev, "failed to remap kgq\n");
+
+       return r;
+}
+
 static int amdgpu_gfx_mes_reset_queue_start(struct amdgpu_ring *ring,
                                             unsigned int vmid,
                                             struct amdgpu_fence 
*timedout_fence,
-                                            bool use_mmio)
+                                            bool use_mmio, bool *need_reinit)
 {
        struct amdgpu_device *adev = ring->adev;
        bool reinit_queue;
@@ -2007,6 +2021,9 @@ static int amdgpu_gfx_mes_reset_queue_start(struct 
amdgpu_ring *ring,
        else
                reinit_queue = use_mmio;
 
+       if (need_reinit)
+               *need_reinit = false;
+
        amdgpu_ring_reset_helper_begin(ring, timedout_fence);
 
        r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, use_mmio, 0);
@@ -2018,13 +2035,9 @@ static int amdgpu_gfx_mes_reset_queue_start(struct 
amdgpu_ring *ring,
                                                  RESET_QUEUES, 0, 0, 0);
                if (r)
                        return r;
-               amdgpu_gfx_mqd_reset_restore(ring);
 
-               r = amdgpu_mes_map_legacy_queue(adev, ring, 0);
-               if (r) {
-                       dev_err(adev->dev, "failed to remap kgq\n");
-                       return r;
-               }
+               if (need_reinit)
+                       *need_reinit = true;
        }
        return 0;
 }
@@ -2034,12 +2047,19 @@ int amdgpu_gfx_mes_reset_queue(struct amdgpu_ring *ring,
                               struct amdgpu_fence *timedout_fence,
                               bool use_mmio)
 {
+       bool need_reinit;
        int r;
 
+       /* Single-queue reset (no suspend/resume): re-add the queue inline. */
        r = amdgpu_gfx_mes_reset_queue_start(ring, vmid, timedout_fence,
-                                             use_mmio);
+                                             use_mmio, &need_reinit);
        if (r)
                return r;
+       if (need_reinit) {
+               r = amdgpu_gfx_mes_reset_queue_reinit(ring);
+               if (r)
+                       return r;
+       }
        return amdgpu_ring_reset_helper_end(ring, timedout_fence);
 }
 
@@ -2239,7 +2259,8 @@ static int amdgpu_gfx_reset_mes_kcq(struct amdgpu_device 
*adev,
                                    struct amdgpu_ring *guilty_ring,
                                    unsigned int db,
                                    struct amdgpu_ring **out_ring,
-                                   struct amdgpu_fence **out_fence)
+                                   struct amdgpu_fence **out_fence,
+                                   bool *out_reinit)
 {
        bool use_mmio = adev->gfx.mec.use_mmio_for_reset;
        struct amdgpu_fence *fence;
@@ -2248,14 +2269,16 @@ static int amdgpu_gfx_reset_mes_kcq(struct 
amdgpu_device *adev,
 
        *out_ring = NULL;
        *out_fence = NULL;
+       *out_reinit = false;
        for (i = 0; i < adev->gfx.num_compute_rings; i++) {
                ring = &adev->gfx.compute_ring[i];
                if (ring == guilty_ring)
                        continue;
                if (ring->doorbell_index == db) {
                        fence = amdgpu_ring_find_guilty_fence(ring);
+                       /* reset + unmap now; re-add (map) is deferred to after 
resume */
                        r = amdgpu_gfx_mes_reset_queue_start(ring, 0, fence,
-                                                             use_mmio);
+                                                             use_mmio, 
out_reinit);
                        if (r)
                                return r;
                        *out_ring = ring;
@@ -2306,12 +2329,16 @@ int amdgpu_gfx_reset_mes_compute(struct amdgpu_device 
*adev,
 fence_reset:
        /* reset the queue this came from if specified */
        if (ring) {
+               bool reinit = false;
+
+               /* reset + unmap now; re-add (map) is deferred to after resume 
*/
                r = amdgpu_gfx_mes_reset_queue_start(ring, 0, guilty_fence,
-                                                     use_mmio);
+                                                     use_mmio, &reinit);
                if (r)
                        goto out;
                deferred_end[n_deferred].ring = ring;
                deferred_end[n_deferred].fence = guilty_fence;
+               deferred_end[n_deferred].reinit = reinit;
                n_deferred++;
        }
        if (uq) {
@@ -2322,6 +2349,7 @@ int amdgpu_gfx_reset_mes_compute(struct amdgpu_device 
*adev,
        for (i = 0; i < num_hung; i++) {
                struct amdgpu_ring *hr = NULL;
                struct amdgpu_fence *hf = NULL;
+               bool hr_reinit = false;
 
                pipe = hqd_info[i].pipe_index;
                queue = hqd_info[i].queue_index;
@@ -2330,12 +2358,13 @@ int amdgpu_gfx_reset_mes_compute(struct amdgpu_device 
*adev,
                /* reset any KCQs */
                r = amdgpu_gfx_reset_mes_kcq(adev, ring,
                                             adev->gfx.mec.mes_hung_db_array[i],
-                                            &hr, &hf);
+                                            &hr, &hf, &hr_reinit);
                if (r)
                        goto out;
                if (hr) {
                        deferred_end[n_deferred].ring = hr;
                        deferred_end[n_deferred].fence = hf;
+                       deferred_end[n_deferred].reinit = hr_reinit;
                        n_deferred++;
                }
                /* reset any KFD queues */
@@ -2372,12 +2401,21 @@ int amdgpu_gfx_reset_mes_compute(struct amdgpu_device 
*adev,
        /* resume all will enable the non-hung queues */
        amdgpu_mes_resume(adev, 0);
 
-       /* Now CP is running again ??? replay backed-up commands and ring
-        * doorbells on each reset queue.
+       /* Now CP is running again ??? for queues that were unmapped during the
+        * reset, re-add (map) them only now that MES is resumed and back to a
+        * normal state, then replay backed-up commands and ring doorbells on
+        * each reset queue.
         */
        for (i = 0; i < n_deferred; i++) {
-               int er = amdgpu_ring_reset_helper_end(deferred_end[i].ring,
-                                                     deferred_end[i].fence);
+               int er;
+
+               if (deferred_end[i].reinit) {
+                       er = 
amdgpu_gfx_mes_reset_queue_reinit(deferred_end[i].ring);
+                       if (er && !r)
+                               r = er;
+               }
+               er = amdgpu_ring_reset_helper_end(deferred_end[i].ring,
+                                                 deferred_end[i].fence);
                if (er && !r)
                        r = er;
        }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index aefd4f03b443..9432107c96a1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -550,6 +550,7 @@ struct amdgpu_gfx {
 struct amdgpu_gfx_deferred_entry {
        struct amdgpu_ring      *ring;
        struct amdgpu_fence     *fence;
+       bool                    reinit;
 };
 
 struct amdgpu_gfx_ras_reg_entry {
-- 
2.49.0

Reply via email to