Implement the update_mqd callback for sdma_v6_0 user queues. SDMA init_mqd
leaves the ring rptr/wptr untouched, so re-run it to rebuild the HQD, then
restore the saved read pointer and forward the user write pointer.

init_mqd also seeds ib_cntl from the live IB_CNTL register, which reads
back IB_ENABLE=0 on a stopped/unmapped queue. Left as-is, the re-mapped
engine drains the ring (rptr advances) but never executes the indirect
buffers, silently dropping the packet queued while disabled. Force
IB_ENABLE on.

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

diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c 
b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
index 3fd3e530c76b..cc923f8531be 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -884,10 +884,39 @@ static int sdma_v6_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_v6_0_mqd_update(struct amdgpu_device *adev, void *mqd,
+                               struct amdgpu_mqd_prop *prop, u64 user_wptr)
+{
+       struct v11_sdma_mqd *m = mqd;
+       u32 saved_rptr = m->sdmax_rlcx_rb_rptr;
+       u32 saved_rptr_hi = m->sdmax_rlcx_rb_rptr_hi;
+
+       sdma_v6_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_v6_0_set_mqd_funcs(struct amdgpu_device *adev)
 {
        adev->mqds[AMDGPU_HW_IP_DMA].mqd_size = sizeof(struct v11_sdma_mqd);
        adev->mqds[AMDGPU_HW_IP_DMA].init_mqd = sdma_v6_0_mqd_init;
+       adev->mqds[AMDGPU_HW_IP_DMA].update_mqd = sdma_v6_0_mqd_update;
 }
 
 /**
-- 
2.49.0

Reply via email to