Reset gfx/compute queue through mmio based on me_id and queue_id.

Signed-off-by: Jesse Zhang <jesse.zh...@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v12_0.h |  2 +
 drivers/gpu/drm/amd/amdgpu/mes_v12_0.c | 88 +++++++++++++++++++++++++-
 2 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.h 
b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.h
index bcc9c72ccbde..f7184b2dc4e8 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.h
@@ -26,4 +26,6 @@
 
 extern const struct amdgpu_ip_block_version gfx_v12_0_ip_block;
 
+int gfx_v12_0_request_gfx_index_mutex(struct amdgpu_device *adev,
+                                     bool req);
 #endif
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c 
b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c
index 0f6635ee84a5..d24a0e7fff15 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c
@@ -24,6 +24,7 @@
 #include <linux/firmware.h>
 #include <linux/module.h>
 #include "amdgpu.h"
+#include "gfx_v12_0.h"
 #include "soc15_common.h"
 #include "soc21.h"
 #include "gc/gc_12_0_0_offset.h"
@@ -350,6 +351,38 @@ static int mes_v12_0_remove_hw_queue(struct amdgpu_mes 
*mes,
                        offsetof(union MESAPI__REMOVE_QUEUE, api_status));
 }
 
+int gfx_v12_0_request_gfx_index_mutex(struct amdgpu_device *adev,
+                                     bool req)
+{
+       u32 i, tmp, val;
+
+       for (i = 0; i < adev->usec_timeout; i++) {
+               /* Request with MeId=2, PipeId=0 */
+               tmp = REG_SET_FIELD(0, CP_GFX_INDEX_MUTEX, REQUEST, req);
+               tmp = REG_SET_FIELD(tmp, CP_GFX_INDEX_MUTEX, CLIENTID, 4);
+               WREG32_SOC15(GC, 0, regCP_GFX_INDEX_MUTEX, tmp);
+
+               val = RREG32_SOC15(GC, 0, regCP_GFX_INDEX_MUTEX);
+               if (req) {
+                       if (val == tmp)
+                               break;
+               } else {
+                       tmp = REG_SET_FIELD(tmp, CP_GFX_INDEX_MUTEX,
+                                           REQUEST, 1);
+
+                       /* unlocked or locked by firmware */
+                       if (val != tmp)
+                               break;
+               }
+               udelay(1);
+       }
+
+       if (i >= adev->usec_timeout)
+               return -EINVAL;
+
+       return 0;
+}
+
 static int mes_v12_0_reset_queue_mmio(struct amdgpu_mes *mes, uint32_t 
queue_type,
                                      uint32_t me_id, uint32_t pipe_id,
                                      uint32_t queue_id, uint32_t vmid)
@@ -360,7 +393,60 @@ static int mes_v12_0_reset_queue_mmio(struct amdgpu_mes 
*mes, uint32_t queue_typ
 
        amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
 
-       if (queue_type == AMDGPU_RING_TYPE_SDMA) {
+       if (queue_type == AMDGPU_RING_TYPE_GFX) {
+               dev_info(adev->dev, "reset gfx queue (%d:%d:%d: vmid:%d)\n",
+                        me_id, pipe_id, queue_id, vmid);
+
+               mutex_lock(&adev->gfx.reset_sem_mutex);
+               gfx_v12_0_request_gfx_index_mutex(adev, true);
+               /* all se allow writes */
+               WREG32_SOC15(GC, 0, regGRBM_GFX_INDEX,
+                            (uint32_t)(0x1 << 
GRBM_GFX_INDEX__SE_BROADCAST_WRITES__SHIFT));
+               value = REG_SET_FIELD(0, CP_VMID_RESET, RESET_REQUEST, 1 << 
vmid);
+               if (pipe_id == 0)
+                       value = REG_SET_FIELD(value, CP_VMID_RESET, 
PIPE0_QUEUES, 1 << queue_id);
+               else
+                       value = REG_SET_FIELD(value, CP_VMID_RESET, 
PIPE1_QUEUES, 1 << queue_id);
+               WREG32_SOC15(GC, 0, regCP_VMID_RESET, value);
+               gfx_v12_0_request_gfx_index_mutex(adev, false);
+               mutex_unlock(&adev->gfx.reset_sem_mutex);
+
+               mutex_lock(&adev->srbm_mutex);
+               soc21_grbm_select(adev, me_id, pipe_id, queue_id, 0);
+               /* wait till dequeue take effects */
+               for (i = 0; i < adev->usec_timeout; i++) {
+                       if (!(RREG32_SOC15(GC, 0, regCP_GFX_HQD_ACTIVE) & 1))
+                               break;
+                       udelay(1);
+               }
+               if (i >= adev->usec_timeout) {
+                       dev_err(adev->dev, "failed to wait on gfx hqd 
deactivate\n");
+                       r = -ETIMEDOUT;
+               }
+
+               soc21_grbm_select(adev, 0, 0, 0, 0);
+               mutex_unlock(&adev->srbm_mutex);
+       } else if (queue_type == AMDGPU_RING_TYPE_COMPUTE) {
+               dev_info(adev->dev, "reset compute queue (%d:%d:%d)\n",
+                        me_id, pipe_id, queue_id);
+               mutex_lock(&adev->srbm_mutex);
+               soc21_grbm_select(adev, me_id, pipe_id, queue_id, 0);
+               WREG32_SOC15(GC, 0, regCP_HQD_DEQUEUE_REQUEST, 0x2);
+               WREG32_SOC15(GC, 0, regSPI_COMPUTE_QUEUE_RESET, 0x1);
+
+               /* wait till dequeue take effects */
+               for (i = 0; i < adev->usec_timeout; i++) {
+                       if (!(RREG32_SOC15(GC, 0, regCP_HQD_ACTIVE) & 1))
+                               break;
+                       udelay(1);
+               }
+               if (i >= adev->usec_timeout) {
+                       dev_err(adev->dev, "failed to wait on hqd 
deactivate\n");
+                       r = -ETIMEDOUT;
+               }
+               soc21_grbm_select(adev, 0, 0, 0, 0);
+               mutex_unlock(&adev->srbm_mutex);
+       } else if (queue_type == AMDGPU_RING_TYPE_SDMA) {
                dev_info(adev->dev, "reset sdma queue (%d:%d:%d)\n",
                         me_id, pipe_id, queue_id);
                switch (me_id) {
-- 
2.25.1

Reply via email to