Implement the update_mqd callback for sdma_v7_0 user queues. SDMA init_mqd
leaves the ring rptr/wptr alone, so re-run it to rebuild the HQD, then
restore the saved read pointer and forward the user write pointer. Force
IB_ENABLE on, since init_mqd seeds ib_cntl from the live IB_CNTL register
which reads back IB_ENABLE=0 on a stopped queue.

Signed-off-by: Jesse Zhang <[email protected]>
Suggested-by: Alexander Deucher <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c | 29 ++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c 
b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
index 2068e2e6e3d6..2ab24d99c5ed 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
@@ -905,10 +905,39 @@ static int sdma_v7_0_mqd_init(struct amdgpu_device *adev, 
void *mqd,
        return 0;
 }
 
+/*
+ * SDMA update_mqd: init_mqd leaves the ring rptr/wptr alone, so re-run it to
+ * rebuild the HQD, then restore the saved rptr and forward the user wptr.
+ */
+static int sdma_v7_0_mqd_update(struct amdgpu_device *adev, void *mqd,
+                               struct amdgpu_mqd_prop *prop, u64 user_wptr)
+{
+       struct v12_sdma_mqd *m = mqd;
+       u32 saved_rptr = m->sdmax_rlcx_rb_rptr;
+       u32 saved_rptr_hi = m->sdmax_rlcx_rb_rptr_hi;
+
+       sdma_v7_0_mqd_init(adev, mqd, prop);
+
+       m->sdmax_rlcx_rb_rptr = saved_rptr;
+       m->sdmax_rlcx_rb_rptr_hi = saved_rptr_hi;
+       m->sdmax_rlcx_rb_wptr = lower_32_bits(user_wptr);
+       m->sdmax_rlcx_rb_wptr_hi = upper_32_bits(user_wptr);
+
+       /*
+        * init_mqd seeds ib_cntl from the live IB_CNTL register, which reads
+        * back IB_ENABLE=0 on a stopped queue; the re-mapped engine would then
+        * drain the ring without executing the IBs. Force IB_ENABLE on.
+        */
+       m->sdmax_rlcx_ib_cntl |= SDMA0_QUEUE0_IB_CNTL__IB_ENABLE_MASK;
+
+       return 0;
+}
+
 static void sdma_v7_0_set_mqd_funcs(struct amdgpu_device *adev)
 {
        adev->mqds[AMDGPU_HW_IP_DMA].mqd_size = sizeof(struct v12_sdma_mqd);
        adev->mqds[AMDGPU_HW_IP_DMA].init_mqd = sdma_v7_0_mqd_init;
+       adev->mqds[AMDGPU_HW_IP_DMA].update_mqd = sdma_v7_0_mqd_update;
 }
 
 /**
-- 
2.49.0

Reply via email to