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

Reply via email to