Implement the update_mqd callback for gfx11 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_v11_0.c | 44 ++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index a447562977ab..1feb7c9ee5c6 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -4256,6 +4256,26 @@ static int gfx_v11_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_v11_0_gfx_mqd_update(struct amdgpu_device *adev, void *m,
+ struct amdgpu_mqd_prop *prop,
+ u64 user_wptr)
+{
+ struct v11_gfx_mqd *mqd = m;
+ u32 saved_rptr = mqd->cp_gfx_hqd_rptr;
+
+ gfx_v11_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_v11_0_kgq_init_queue(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
@@ -4477,6 +4497,26 @@ static int gfx_v11_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_v11_0_compute_mqd_update(struct amdgpu_device *adev, void *m,
+ struct amdgpu_mqd_prop *prop,
+ u64 user_wptr)
+{
+ struct v11_compute_mqd *mqd = m;
+ u32 saved_rptr = mqd->cp_hqd_pq_rptr;
+
+ gfx_v11_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_v11_0_kiq_init_register(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
@@ -7271,11 +7311,15 @@ static void gfx_v11_0_set_mqd_funcs(struct
amdgpu_device *adev)
sizeof(struct v11_gfx_mqd);
adev->mqds[AMDGPU_HW_IP_GFX].init_mqd =
gfx_v11_0_gfx_mqd_init;
+ adev->mqds[AMDGPU_HW_IP_GFX].update_mqd =
+ gfx_v11_0_gfx_mqd_update;
/* set compute eng mqd */
adev->mqds[AMDGPU_HW_IP_COMPUTE].mqd_size =
sizeof(struct v11_compute_mqd);
adev->mqds[AMDGPU_HW_IP_COMPUTE].init_mqd =
gfx_v11_0_compute_mqd_init;
+ adev->mqds[AMDGPU_HW_IP_COMPUTE].update_mqd =
+ gfx_v11_0_compute_mqd_update;
}
static void gfx_v11_0_set_user_wgp_inactive_bitmap_per_sh(struct amdgpu_device
*adev,
--
2.49.0