Set prop->modify and prop->user_wptr (read from the wptr poll BO) and
call init_mqd, so a re-enabled compute queue keeps its context-saved
rptr and resumes at the first un-consumed packet.
Also set modify=false on the create and kernel-ring
(amdgpu_ring_to_mqd_prop) paths, so every init_mqd caller states its own
value rather than relying on the zeroed prop.
v3: set the mqd_prop modify flag and call init_mqd instead of a separate
update_mqd callback, per review.
Signed-off-by: Jesse Zhang <[email protected]>
Suggested-by: Alexander Deucher <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 2 ++
drivers/gpu/drm/amd/amdgpu/mes_userqueue.c | 20 +++++++++++++++++++-
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index 686c92e96025..9fd0ab0be40e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -840,6 +840,8 @@ static void amdgpu_ring_to_mqd_prop(struct amdgpu_ring
*ring,
prop->use_doorbell = ring->use_doorbell;
prop->doorbell_index = ring->doorbell_index;
prop->kernel_queue = true;
+ /* kernel rings always build the MQD from scratch, never a MODIFY */
+ prop->modify = false;
/* map_queues packet doesn't need activate the queue,
* so only kiq need set this field.
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
index 82bb4369451e..c6ac3194e4da 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
@@ -479,6 +479,7 @@ static int mes_userq_mqd_create(struct
amdgpu_usermode_queue *queue,
userq_props->use_doorbell = true;
userq_props->doorbell_index = queue->doorbell_index;
userq_props->fence_address = queue->fence_drv->gpu_addr;
+ userq_props->modify = false;
if (queue->queue_type == AMDGPU_HW_IP_COMPUTE) {
struct drm_amdgpu_userq_mqd_compute_gfx11 *compute_mqd;
@@ -681,6 +682,20 @@ static int mes_userq_mqd_create(struct
amdgpu_usermode_queue *queue,
return r;
}
+/* Read the queue's live user wptr from its poll BO; 0 if not mapped. */
+static u64 mes_userq_read_user_wptr(struct amdgpu_usermode_queue *queue)
+{
+ u64 user_wptr = 0;
+ void *wc = NULL;
+
+ if (queue->wptr_obj.obj &&
+ !amdgpu_bo_kmap(queue->wptr_obj.obj, &wc) && wc) {
+ user_wptr = *(volatile u64 *)wc;
+ amdgpu_bo_kunmap(queue->wptr_obj.obj);
+ }
+ return user_wptr;
+}
+
static int mes_userq_compute_mqd_update(struct amdgpu_usermode_queue *queue,
struct drm_amdgpu_userq_in *args_in)
{
@@ -707,8 +722,11 @@ static int mes_userq_compute_mqd_update(struct
amdgpu_usermode_queue *queue,
userq_props->queue_size = args_in->queue_size;
userq_props->hqd_base_gpu_addr = args_in->queue_va;
+ userq_props->modify = true;
+ userq_props->user_wptr = mes_userq_read_user_wptr(queue);
- retval = mqd_hw_default->init_mqd(adev, (void *)queue->mqd.cpu_ptr,
userq_props);
+ retval = mqd_hw_default->init_mqd(adev, (void *)queue->mqd.cpu_ptr,
+ userq_props);
free:
kfree(compute_mqd_v11);
--
2.49.0