Call the per-IP update_mqd callback instead of init_mqd for a compute
MODIFY, so a queue re-enabled after a queue_percentage == 0 disable keeps
its ring position instead of wedging into a GPU reset (see the update_mqd
callback commit for why). Add mes_userq_read_user_wptr() to read the
current user wptr and forward it to the callback.

Signed-off-by: Jesse Zhang <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/mes_userqueue.c | 28 +++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c 
b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
index 82bb4369451e..f2742fa28dc6 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
@@ -681,6 +681,25 @@ static int mes_userq_mqd_create(struct 
amdgpu_usermode_queue *queue,
        return r;
 }
 
+/*
+ * Read the queue's current user wptr from its wptr poll BO. Packets queued
+ * while the queue was disabled advanced this value but not the MQD; the per-IP
+ * update_mqd callback forwards it back into the MQD so a re-enabled queue 
picks
+ * the work up. Returns 0 if the BO is 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)
 {
@@ -695,6 +714,11 @@ static int mes_userq_compute_mqd_update(struct 
amdgpu_usermode_queue *queue,
                return -EINVAL;
        }
 
+       if (!mqd_hw_default->update_mqd) {
+               DRM_ERROR("Compute MQD update not supported on this IP\n");
+               return -EOPNOTSUPP;
+       }
+
        compute_mqd_v11 = memdup_user(u64_to_user_ptr(args_in->mqd), 
args_in->mqd_size);
        if (IS_ERR(compute_mqd_v11)) {
                DRM_ERROR("Failed to read user MQD\n");
@@ -708,7 +732,9 @@ 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;
 
-       retval = mqd_hw_default->init_mqd(adev, (void *)queue->mqd.cpu_ptr, 
userq_props);
+       retval = mqd_hw_default->update_mqd(adev, (void *)queue->mqd.cpu_ptr,
+                                           userq_props,
+                                           mes_userq_read_user_wptr(queue));
 
 free:
        kfree(compute_mqd_v11);
-- 
2.49.0

Reply via email to