Implement the update_mqd callback for gfx12 compute and GFX user queues.
Save the read pointer, re-run init_mqd to rebuild the HQD, then restore
the saved read pointer and forward the write pointer to the user wptr, so
a re-enabled queue resumes at the first un-consumed packet rather than
replaying the ring from 0.

v2: rebuild the HQD via init_mqd and save/restore the rptr, matching the
    SDMA update_mqd style, instead of patching individual MQD fields in
    place. Keeps all update_mqd callbacks consistent.

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

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c 
b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index a434b665d913..7395719d593c 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -3096,6 +3096,26 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device 
*adev, void *m,
        return 0;
 }
 
+/*
+ * GFX update_mqd: init_mqd resets the ring rptr/wptr, so re-run it to rebuild
+ * the HQD, then restore the saved rptr and forward the user wptr.
+ */
+static int gfx_v12_0_gfx_mqd_update(struct amdgpu_device *adev, void *m,
+                                   struct amdgpu_mqd_prop *prop,
+                                   u64 user_wptr)
+{
+       struct v12_gfx_mqd *mqd = m;
+       u32 saved_rptr = mqd->cp_gfx_hqd_rptr;
+
+       gfx_v12_0_gfx_mqd_init(adev, mqd, prop);
+
+       mqd->cp_gfx_hqd_rptr = saved_rptr;
+       mqd->cp_gfx_hqd_wptr = lower_32_bits(user_wptr);
+       mqd->cp_gfx_hqd_wptr_hi = upper_32_bits(user_wptr);
+
+       return 0;
+}
+
 static int gfx_v12_0_kgq_init_queue(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
@@ -3334,6 +3354,26 @@ static int gfx_v12_0_compute_mqd_init(struct 
amdgpu_device *adev, void *m,
        return 0;
 }
 
+/*
+ * Compute update_mqd: init_mqd resets the ring rptr/wptr, so re-run it to
+ * rebuild the HQD, then restore the saved rptr and forward the user wptr.
+ */
+static int gfx_v12_0_compute_mqd_update(struct amdgpu_device *adev, void *m,
+                                       struct amdgpu_mqd_prop *prop,
+                                       u64 user_wptr)
+{
+       struct v12_compute_mqd *mqd = m;
+       u32 saved_rptr = mqd->cp_hqd_pq_rptr;
+
+       gfx_v12_0_compute_mqd_init(adev, mqd, prop);
+
+       mqd->cp_hqd_pq_rptr = saved_rptr;
+       mqd->cp_hqd_pq_wptr_lo = lower_32_bits(user_wptr);
+       mqd->cp_hqd_pq_wptr_hi = upper_32_bits(user_wptr);
+
+       return 0;
+}
+
 static int gfx_v12_0_kiq_init_register(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
@@ -5543,11 +5583,15 @@ static void gfx_v12_0_set_mqd_funcs(struct 
amdgpu_device *adev)
                sizeof(struct v12_gfx_mqd);
        adev->mqds[AMDGPU_HW_IP_GFX].init_mqd =
                gfx_v12_0_gfx_mqd_init;
+       adev->mqds[AMDGPU_HW_IP_GFX].update_mqd =
+               gfx_v12_0_gfx_mqd_update;
        /* set compute eng mqd */
        adev->mqds[AMDGPU_HW_IP_COMPUTE].mqd_size =
                sizeof(struct v12_compute_mqd);
        adev->mqds[AMDGPU_HW_IP_COMPUTE].init_mqd =
                gfx_v12_0_compute_mqd_init;
+       adev->mqds[AMDGPU_HW_IP_COMPUTE].update_mqd =
+               gfx_v12_0_compute_mqd_update;
 }
 
 static void gfx_v12_0_set_user_wgp_inactive_bitmap_per_sh(struct amdgpu_device 
*adev,
-- 
2.49.0

Reply via email to