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