[PATCH 6/8] drm/amdgpu: Map userqueue into HW

Shashank Sharma shashank.sharma at amd.com
Fri Feb 3 21:54:07 UTC 2023


From: Shashank Sharma <contactshashanksharma at gmail.com>

This patch adds new fptrs to prepare the usermode queue to be
mapped or unmapped into the HW. After this mapping, the queue
will be ready to accept the workload.

V1: Addressed review comments from Alex on the RFC patch series
    - Map/Unmap should be IP specific.

Cc: Alex Deucher <alexander.deucher at amd.com>
Cc: Christian Koenig <christian.koenig at amd.com>
Signed-off-by: Shashank Sharma <shashank.sharma at amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 57 +++++++++++++++++++
 .../amd/amdgpu/amdgpu_userqueue_mqd_gfx_v11.c | 47 +++++++++++++++
 .../gpu/drm/amd/include/amdgpu_userqueue.h    |  2 +
 3 files changed, 106 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
index 18281b3a51f1..cbfe2608c040 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
@@ -42,6 +42,53 @@ static struct amdgpu_usermode_queue
     return idr_find(&uq_mgr->userq_idr, qid);
 }
 
+static void
+amdgpu_userqueue_unmap(struct amdgpu_userq_mgr *uq_mgr,
+                     struct amdgpu_usermode_queue *queue)
+{
+    int r;
+    struct amdgpu_device *adev = uq_mgr->adev;
+    struct mes_remove_queue_input remove_request;
+
+    uq_mgr->userq_mqd_funcs->prepare_unmap(uq_mgr, queue, (void *)&remove_request);
+
+    amdgpu_mes_lock(&adev->mes);
+    r = adev->mes.funcs->remove_hw_queue(&adev->mes, &remove_request);
+    amdgpu_mes_unlock(&adev->mes);
+    if (r) {
+        DRM_ERROR("Failed to unmap usermode queue %d\n", queue->queue_id);
+        return;
+    }
+
+    DRM_DEBUG_DRIVER("Usermode queue %d unmapped\n", queue->queue_id);
+}
+
+static int
+amdgpu_userqueue_map(struct amdgpu_userq_mgr *uq_mgr,
+                     struct amdgpu_usermode_queue *queue)
+{
+    int r;
+    struct amdgpu_device *adev = uq_mgr->adev;
+    struct mes_add_queue_input add_request;
+
+    r = uq_mgr->userq_mqd_funcs->prepare_map(uq_mgr, queue, (void *)&add_request);
+    if (r) {
+        DRM_ERROR("Failed to map userqueue\n");
+        return r;
+    }
+
+    amdgpu_mes_lock(&adev->mes);
+    r = adev->mes.funcs->add_hw_queue(&adev->mes, &add_request);
+    amdgpu_mes_unlock(&adev->mes);
+    if (r) {
+        DRM_ERROR("Failed to map queue in HW, err (%d)\n", r);
+        return r;
+    }
+
+    DRM_DEBUG_DRIVER("Queue %d mapped successfully\n", queue->queue_id);
+    return 0;
+}
+
 static void
 amdgpu_userqueue_destroy_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
                                    struct amdgpu_usermode_queue *queue)
@@ -170,12 +217,21 @@ static int amdgpu_userqueue_create(struct drm_file *filp, union drm_amdgpu_userq
         goto free_mqd;
     }
 
+    r = amdgpu_userqueue_map(uq_mgr, queue);
+    if (r) {
+        DRM_ERROR("Failed to map userqueue\n");
+        goto free_ctx;
+    }
+
     list_add_tail(&queue->userq_node, &uq_mgr->userq_list);
     args->out.q_id = queue->queue_id;
     args->out.flags = 0;
     mutex_unlock(&uq_mgr->userq_mutex);
     return 0;
 
+free_ctx:
+    amdgpu_userqueue_destroy_ctx_space(uq_mgr, queue);
+
 free_mqd:
     amdgpu_userqueue_destroy_mqd(uq_mgr, queue);
 
@@ -201,6 +257,7 @@ static void amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
     }
 
     mutex_lock(&uq_mgr->userq_mutex);
+    amdgpu_userqueue_unmap(uq_mgr, queue);
     amdgpu_userqueue_destroy_ctx_space(uq_mgr, queue);
     amdgpu_userqueue_destroy_mqd(uq_mgr, queue);
     amdgpu_userqueue_free_index(uq_mgr, queue->queue_id);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue_mqd_gfx_v11.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue_mqd_gfx_v11.c
index 687f90a587e3..d317bb600fd9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue_mqd_gfx_v11.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue_mqd_gfx_v11.c
@@ -24,6 +24,7 @@
 #include "amdgpu_userqueue.h"
 #include "v11_structs.h"
 #include "amdgpu_mes.h"
+#include "mes_api_def.h"
 #include "gc/gc_11_0_0_offset.h"
 #include "gc/gc_11_0_0_sh_mask.h"
 
@@ -239,6 +240,50 @@ static void amdgpu_userq_gfx_v11_ctx_destroy(struct amdgpu_userq_mgr *uq_mgr,
                           &pctx->cpu_ptr);
 }
 
+static int
+amdgpu_userq_gfx_v11_prepare_map(struct amdgpu_userq_mgr *uq_mgr,
+                                 struct amdgpu_usermode_queue *queue,
+                                 void *q_input)
+{
+    struct amdgpu_device *adev = uq_mgr->adev;
+    struct mes_add_queue_input *queue_input = q_input;
+
+    memset(queue_input, 0x0, sizeof(struct mes_add_queue_input));
+
+    queue_input->process_va_start = 0;
+    queue_input->process_va_end = (adev->vm_manager.max_pfn - 1) << AMDGPU_GPU_PAGE_SHIFT;
+    queue_input->process_quantum = 100000; /* 10ms */
+    queue_input->gang_quantum = 10000; /* 1ms */
+    queue_input->paging = false;
+
+    queue_input->gang_context_addr = queue->gang_ctx.gpu_addr;
+    queue_input->process_context_addr = queue->proc_ctx.gpu_addr;
+    queue_input->inprocess_gang_priority = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
+    queue_input->gang_global_priority_level = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
+
+    queue_input->process_id = queue->pasid;
+    queue_input->queue_type = queue->queue_type;
+    queue_input->mqd_addr = queue->mqd_gpu_addr;
+    queue_input->wptr_addr = queue->wptr_gpu_addr;
+    queue_input->wptr_mc_addr = queue->wptr_gpu_addr << AMDGPU_GPU_PAGE_SHIFT;
+    queue_input->queue_size = queue->queue_size >> 2;
+    queue_input->doorbell_offset = queue->doorbell_index;
+    queue_input->page_table_base_addr = amdgpu_gmc_pd_addr(queue->vm->root.bo);
+    return 0;
+}
+
+static void
+amdgpu_userq_gfx_v11_prepare_unmap(struct amdgpu_userq_mgr *uq_mgr,
+                                   struct amdgpu_usermode_queue *queue,
+                                   void *q_input)
+{
+    struct mes_remove_queue_input *queue_input = q_input;
+
+    memset(queue_input, 0x0, sizeof(struct mes_remove_queue_input));
+    queue_input->doorbell_offset = queue->doorbell_index;
+    queue_input->gang_context_addr = queue->gang_ctx.gpu_addr;
+}
+
 static int amdgpu_userq_gfx_v11_mqd_size(struct amdgpu_userq_mgr *uq_mgr)
 {
     return sizeof(struct v11_gfx_mqd);
@@ -250,4 +295,6 @@ const struct amdgpu_userq_mqd_funcs userq_gfx_v11_mqd_funcs = {
     .mqd_destroy = amdgpu_userq_gfx_v11_mqd_destroy,
     .ctx_create = amdgpu_userq_gfx_v11_ctx_create,
     .ctx_destroy = amdgpu_userq_gfx_v11_ctx_destroy,
+    .prepare_map = amdgpu_userq_gfx_v11_prepare_map,
+    .prepare_unmap = amdgpu_userq_gfx_v11_prepare_unmap,
 };
diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
index 3adcd31618f7..202fac237501 100644
--- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
+++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
@@ -82,6 +82,8 @@ struct amdgpu_userq_mqd_funcs {
 	void (*mqd_destroy)(struct amdgpu_userq_mgr *, struct amdgpu_usermode_queue *);
 	int (*ctx_create)(struct amdgpu_userq_mgr *, struct amdgpu_usermode_queue *);
 	void (*ctx_destroy)(struct amdgpu_userq_mgr *, struct amdgpu_usermode_queue *);
+	int (*prepare_map)(struct amdgpu_userq_mgr *, struct amdgpu_usermode_queue *, void *);
+	void (*prepare_unmap)(struct amdgpu_userq_mgr *, struct amdgpu_usermode_queue *, void *);
 };
 
 int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev);
-- 
2.34.1



More information about the amd-gfx mailing list