AMD-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 1/6] drm/amdgpu: add mqd_update callback to AMDGPU user queue interface
@ 2026-01-28 10:58 Jesse.Zhang
  2026-01-28 10:58 ` [PATCH v4 2/6] drm/amdgpu: Add CU mask support for MQD properties Jesse.Zhang
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Jesse.Zhang @ 2026-01-28 10:58 UTC (permalink / raw)
  To: amd-gfx
  Cc: Alexander.Deucher, Christian Koenig, Jesse.Zhang, Alex Deucher,
	Jesse Zhang

Extend the AMDGPU user queue function interface to support MQD
updates by adding an mqd_update callback.

v2: add the input paramter struct drm_amdgpu_userq_in in mqd_update

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
index 95ace14e458c..833468b58603 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
@@ -79,6 +79,8 @@ struct amdgpu_usermode_queue {
 struct amdgpu_userq_funcs {
 	int (*mqd_create)(struct amdgpu_usermode_queue *queue,
 			  struct drm_amdgpu_userq_in *args);
+	int (*mqd_update)(struct amdgpu_usermode_queue *queue,
+			  struct drm_amdgpu_userq_in *args);
 	void (*mqd_destroy)(struct amdgpu_usermode_queue *uq);
 	int (*unmap)(struct amdgpu_usermode_queue *queue);
 	int (*map)(struct amdgpu_usermode_queue *queue);
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 2/6] drm/amdgpu: Add CU mask support for MQD properties
  2026-01-28 10:58 [PATCH v4 1/6] drm/amdgpu: add mqd_update callback to AMDGPU user queue interface Jesse.Zhang
@ 2026-01-28 10:58 ` Jesse.Zhang
  2026-01-28 10:58 ` [PATCH v4 3/6] drm/amdgpu/gfx11: add CU mask support for compute MQD initialization Jesse.Zhang
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Jesse.Zhang @ 2026-01-28 10:58 UTC (permalink / raw)
  To: amd-gfx
  Cc: Alexander.Deucher, Christian Koenig, Jesse.Zhang, Alex Deucher,
	Jesse Zhang

Add new fields to the amdgpu_mqd_prop structure to track CU (Compute Unit)
mask information, including the mask itself, count, flags, and a flag to
indicate if user-specified CU masking is active.

v2: Create a generic function amdgpu_gfx_mqd_symmetrically_map_cu_mask()

Suggested-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h     | 10 +++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 49 +++++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h |  2 +
 3 files changed, 61 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 11a36c132905..a8f4f73fa0ce 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -789,6 +789,12 @@ struct amd_powerplay {
 					  (rid == 0x01) || \
 					  (rid == 0x10))))
 
+enum amdgpu_mqd_update_flag {
+       AMDGPU_UPDATE_FLAG_DBG_WA_ENABLE = 1,
+       AMDGPU_UPDATE_FLAG_DBG_WA_DISABLE = 2,
+       AMDGPU_UPDATE_FLAG_IS_GWS = 4, /* quirk for gfx9 IP */
+};
+
 struct amdgpu_mqd_prop {
 	uint64_t mqd_gpu_addr;
 	uint64_t hqd_base_gpu_addr;
@@ -809,6 +815,10 @@ struct amdgpu_mqd_prop {
 	uint64_t fence_address;
 	bool tmz_queue;
 	bool kernel_queue;
+	uint32_t *cu_mask;
+	uint32_t cu_mask_count;
+	uint32_t cu_flags;
+	bool is_user_cu_masked;
 };
 
 struct amdgpu_mqd {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index 6abe5103a78d..73e6988cb703 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -501,6 +501,55 @@ void amdgpu_gfx_mqd_sw_fini(struct amdgpu_device *adev, int xcc_id)
 			      &ring->mqd_ptr);
 }
 
+void amdgpu_gfx_mqd_symmetrically_map_cu_mask(struct amdgpu_device *adev, const uint32_t *cu_mask,
+					      uint32_t cu_mask_count, uint32_t *se_mask)
+{
+	struct amdgpu_cu_info *cu_info = &adev->gfx.cu_info;
+	struct amdgpu_gfx_config *gfx_info = &adev->gfx.config;
+	uint32_t cu_per_sh[8][4] = {0};
+	int i, se, sh, cu, cu_bitmap_sh_mul;
+	int xcc_inst = ffs(adev->gfx.xcc_mask) - 1;
+	bool wgp_mode_req = amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 0, 0);
+	int cu_inc = wgp_mode_req ? 2 : 1;
+	uint32_t en_mask = wgp_mode_req ? 0x3 : 0x1;
+	int num_xcc, inc, inst = 0;
+
+	if (xcc_inst < 0)
+		xcc_inst = 0;
+
+	num_xcc = hweight16(adev->gfx.xcc_mask);
+	if (!num_xcc)
+		num_xcc = 1;
+
+	inc = cu_inc * num_xcc;
+
+	cu_bitmap_sh_mul = 2;
+
+	for (se = 0; se < gfx_info->max_shader_engines; se++)
+		for (sh = 0; sh < gfx_info->max_sh_per_se; sh++)
+			cu_per_sh[se][sh] = hweight32(
+				cu_info->bitmap[xcc_inst][se % 4][sh + (se / 4) *
+				cu_bitmap_sh_mul]);
+
+	for (i = 0; i < gfx_info->max_shader_engines; i++)
+		se_mask[i] = 0;
+
+	i = inst;
+	for (cu = 0; cu < 16; cu += cu_inc) {
+		for (sh = 0; sh < gfx_info->max_sh_per_se; sh++) {
+			for (se = 0; se < gfx_info->max_shader_engines; se++) {
+				if (cu_per_sh[se][sh] > cu) {
+					if ((i / 32) < cu_mask_count && (cu_mask[i / 32] & (1 << (i % 32))))
+						se_mask[se] |= en_mask << (cu + sh * 16);
+					i += inc;
+					if (i >= cu_mask_count * 32)
+						return;
+				}
+			}
+		}
+	}
+}
+
 int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id)
 {
 	struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index 585cc8e81bb2..720ed3a2c78c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -583,6 +583,8 @@ int amdgpu_gfx_kiq_init(struct amdgpu_device *adev,
 int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev,
 			   unsigned mqd_size, int xcc_id);
 void amdgpu_gfx_mqd_sw_fini(struct amdgpu_device *adev, int xcc_id);
+void amdgpu_gfx_mqd_symmetrically_map_cu_mask(struct amdgpu_device *adev, const uint32_t *cu_mask,
+					      uint32_t cu_mask_count, uint32_t *se_mask);
 int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id);
 int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev, int xcc_id);
 int amdgpu_gfx_disable_kgq(struct amdgpu_device *adev, int xcc_id);
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 3/6] drm/amdgpu/gfx11: add CU mask support for compute MQD initialization
  2026-01-28 10:58 [PATCH v4 1/6] drm/amdgpu: add mqd_update callback to AMDGPU user queue interface Jesse.Zhang
  2026-01-28 10:58 ` [PATCH v4 2/6] drm/amdgpu: Add CU mask support for MQD properties Jesse.Zhang
@ 2026-01-28 10:58 ` Jesse.Zhang
  2026-01-28 10:58 ` [PATCH v4 4/6] drm/amdgpu/gfx12: " Jesse.Zhang
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Jesse.Zhang @ 2026-01-28 10:58 UTC (permalink / raw)
  To: amd-gfx
  Cc: Alexander.Deucher, Christian Koenig, Jesse.Zhang, Alex Deucher,
	Jesse Zhang

Extend the GFX11 compute MQD initialization to support
Compute Unit (CU) masking for fine-grained resource allocation.
This allows compute queues to be limited to specific CUs for
performance isolation and debugging purposes.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 33 ++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 3a4ca104b161..55d98b1a9ac5 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -4238,6 +4238,37 @@ static int gfx_v11_0_cp_async_gfx_ring_resume(struct amdgpu_device *adev)
 	return gfx_v11_0_cp_gfx_start(adev);
 }
 
+static void gfx_v11_0_compute_mqd_set_cu_mask(struct amdgpu_device *adev,
+					      struct v11_compute_mqd *mqd,
+					      struct amdgpu_mqd_prop *prop)
+{
+	uint32_t se_mask[8] = {0};
+	uint32_t wa_mask;
+	bool has_wa_flag = prop->cu_flags & (AMDGPU_UPDATE_FLAG_DBG_WA_ENABLE |
+					  AMDGPU_UPDATE_FLAG_DBG_WA_DISABLE);
+
+	if (!has_wa_flag && (!prop->cu_mask || !prop->cu_mask_count))
+		return;
+
+	if (has_wa_flag) {
+		wa_mask = (prop->cu_flags & AMDGPU_UPDATE_FLAG_DBG_WA_ENABLE) ?
+			  0xffff : 0xffffffff;
+		mqd->compute_static_thread_mgmt_se0 = wa_mask;
+		mqd->compute_static_thread_mgmt_se1 = wa_mask;
+		mqd->compute_static_thread_mgmt_se2 = wa_mask;
+		mqd->compute_static_thread_mgmt_se3 = wa_mask;
+		return;
+	}
+
+	amdgpu_gfx_mqd_symmetrically_map_cu_mask(adev, prop->cu_mask,
+						prop->cu_mask_count, se_mask);
+
+	mqd->compute_static_thread_mgmt_se0 = se_mask[0];
+	mqd->compute_static_thread_mgmt_se1 = se_mask[1];
+	mqd->compute_static_thread_mgmt_se2 = se_mask[2];
+	mqd->compute_static_thread_mgmt_se3 = se_mask[3];
+}
+
 static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
 				      struct amdgpu_mqd_prop *prop)
 {
@@ -4372,6 +4403,8 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
 	/* set UQ fenceaddress */
 	mqd->fence_address_lo = lower_32_bits(prop->fence_address);
 	mqd->fence_address_hi = upper_32_bits(prop->fence_address);
+	/* set CU mask */
+	gfx_v11_0_compute_mqd_set_cu_mask(adev, mqd, prop);
 
 	return 0;
 }
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 4/6] drm/amdgpu/gfx12: add CU mask support for compute MQD initialization
  2026-01-28 10:58 [PATCH v4 1/6] drm/amdgpu: add mqd_update callback to AMDGPU user queue interface Jesse.Zhang
  2026-01-28 10:58 ` [PATCH v4 2/6] drm/amdgpu: Add CU mask support for MQD properties Jesse.Zhang
  2026-01-28 10:58 ` [PATCH v4 3/6] drm/amdgpu/gfx11: add CU mask support for compute MQD initialization Jesse.Zhang
@ 2026-01-28 10:58 ` Jesse.Zhang
  2026-01-28 10:58 ` [PATCH v4 5/6] drm/amdgpu: add MQD update support for user mode compute queues Jesse.Zhang
  2026-01-28 10:58 ` [PATCH v4 6/6] drm/amdgpu: add MODIFY operation for " Jesse.Zhang
  4 siblings, 0 replies; 10+ messages in thread
From: Jesse.Zhang @ 2026-01-28 10:58 UTC (permalink / raw)
  To: amd-gfx
  Cc: Alexander.Deucher, Christian Koenig, Jesse.Zhang, Alex Deucher,
	Jesse Zhang

Extend the GFX12 compute MQD initialization to support
Compute Unit (CU) masking for fine-grained resource allocation.
This allows compute queues to be limited to specific CUs for
performance isolation and debugging purposes.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 33 ++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index 6cd16f016c37..73478dd0f6ad 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -3110,6 +3110,37 @@ static int gfx_v12_0_cp_async_gfx_ring_resume(struct amdgpu_device *adev)
 	return gfx_v12_0_cp_gfx_start(adev);
 }
 
+static void gfx_v12_0_compute_mqd_set_cu_mask(struct amdgpu_device *adev,
+					      struct v12_compute_mqd *mqd,
+					      struct amdgpu_mqd_prop *prop)
+{
+	uint32_t se_mask[8] = {0};
+	uint32_t wa_mask;
+	bool has_wa_flag = prop->cu_flags & (AMDGPU_UPDATE_FLAG_DBG_WA_ENABLE |
+					  AMDGPU_UPDATE_FLAG_DBG_WA_DISABLE);
+
+	if (!has_wa_flag && (!prop->cu_mask || !prop->cu_mask_count))
+		return;
+
+	if (has_wa_flag) {
+		wa_mask = (prop->cu_flags & AMDGPU_UPDATE_FLAG_DBG_WA_ENABLE) ?
+			  0xffff : 0xffffffff;
+		mqd->compute_static_thread_mgmt_se0 = wa_mask;
+		mqd->compute_static_thread_mgmt_se1 = wa_mask;
+		mqd->compute_static_thread_mgmt_se2 = wa_mask;
+		mqd->compute_static_thread_mgmt_se3 = wa_mask;
+		return;
+	}
+
+	amdgpu_gfx_mqd_symmetrically_map_cu_mask(adev, prop->cu_mask,
+						prop->cu_mask_count, se_mask);
+
+	mqd->compute_static_thread_mgmt_se0 = se_mask[0];
+	mqd->compute_static_thread_mgmt_se1 = se_mask[1];
+	mqd->compute_static_thread_mgmt_se2 = se_mask[2];
+	mqd->compute_static_thread_mgmt_se3 = se_mask[3];
+}
+
 static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
 				      struct amdgpu_mqd_prop *prop)
 {
@@ -3243,6 +3274,8 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
 	/* set UQ fenceaddress */
 	mqd->fence_address_lo = lower_32_bits(prop->fence_address);
 	mqd->fence_address_hi = upper_32_bits(prop->fence_address);
+	/* set CU mask */
+	gfx_v12_0_compute_mqd_set_cu_mask(adev, mqd, prop);
 
 	return 0;
 }
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 5/6] drm/amdgpu: add MQD update support for user mode compute queues
  2026-01-28 10:58 [PATCH v4 1/6] drm/amdgpu: add mqd_update callback to AMDGPU user queue interface Jesse.Zhang
                   ` (2 preceding siblings ...)
  2026-01-28 10:58 ` [PATCH v4 4/6] drm/amdgpu/gfx12: " Jesse.Zhang
@ 2026-01-28 10:58 ` Jesse.Zhang
  2026-02-03 14:22   ` Lazar, Lijo
  2026-01-28 10:58 ` [PATCH v4 6/6] drm/amdgpu: add MODIFY operation for " Jesse.Zhang
  4 siblings, 1 reply; 10+ messages in thread
From: Jesse.Zhang @ 2026-01-28 10:58 UTC (permalink / raw)
  To: amd-gfx
  Cc: Alexander.Deucher, Christian Koenig, Jesse.Zhang, Alex Deucher,
	Jesse Zhang

The update functionality allows dynamic adjustment of queue properties at runtime,
enabling better resource management and performance tuning for compute workloads.

v2: Return an error for non-compute queues. (Alex)
    remove the parameter minfo

V3: put the new paramters in drm_amdgpu_userq_mqd_compute_gfx11. (Alex)
v4: move the define AMDGPU_USERQ_OP_MODIFY to patch 6/6 (Alex)
    add the props input paramter to amdgpu_userq_set_compute_mqd

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Suggested-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h        |   3 +
 drivers/gpu/drm/amd/amdgpu/mes_userqueue.c | 166 ++++++++++++++++++++-
 include/uapi/drm/amdgpu_drm.h              |  28 ++++
 3 files changed, 194 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index a8f4f73fa0ce..ad136145316b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -819,6 +819,9 @@ struct amdgpu_mqd_prop {
 	uint32_t cu_mask_count;
 	uint32_t cu_flags;
 	bool is_user_cu_masked;
+	uint32_t queue_percentage;
+	/* used in gfx9 and gfx12.1 */
+	uint32_t pm4_target_xcc;
 };
 
 struct amdgpu_mqd {
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
index f2309d72bbe6..d5251f2d7613 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
@@ -30,6 +30,26 @@
 #define AMDGPU_USERQ_PROC_CTX_SZ PAGE_SIZE
 #define AMDGPU_USERQ_GANG_CTX_SZ PAGE_SIZE
 
+/* Mapping queue priority to pipe priority, indexed by queue priority */
+int amdgpu_userq_pipe_priority_map[] = {
+	AMDGPU_RING_PRIO_0,
+	AMDGPU_RING_PRIO_0,
+	AMDGPU_RING_PRIO_0,
+	AMDGPU_RING_PRIO_0,
+	AMDGPU_RING_PRIO_0,
+	AMDGPU_RING_PRIO_0,
+	AMDGPU_RING_PRIO_0,
+	AMDGPU_RING_PRIO_1,
+	AMDGPU_RING_PRIO_1,
+	AMDGPU_RING_PRIO_1,
+	AMDGPU_RING_PRIO_1,
+	AMDGPU_RING_PRIO_2,
+	AMDGPU_RING_PRIO_2,
+	AMDGPU_RING_PRIO_2,
+	AMDGPU_RING_PRIO_2,
+	AMDGPU_RING_PRIO_2
+};
+
 static int
 mes_userq_map_gtt_bo_to_gart(struct amdgpu_bo *bo)
 {
@@ -272,6 +292,105 @@ static int mes_userq_detect_and_reset(struct amdgpu_device *adev,
 	return r;
 }
 
+/**
+ * amdgpu_userq_set_compute_mqd - Parse compute MQD and update queue props
+ * @queue: Target user mode queue
+ * @props: Queue property structure to be updated
+ * @args: User queue input arguments
+ * @uq_mgr: User queue manager (for logging)
+ *
+ * This function only parses and validates user input, updating queue props
+ * (no hardware MQD configuration - that's handled in MES layer)
+ * Returns: 0 on success, negative error code on failure
+ */
+static int amdgpu_userq_set_compute_mqd(struct amdgpu_usermode_queue *queue,
+					struct amdgpu_mqd_prop *props,
+					struct drm_amdgpu_userq_mqd_compute_gfx11 * compute_mqd)
+{
+	struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
+	struct amdgpu_device *adev = uq_mgr->adev;
+	const int max_num_cus = 1024;
+	size_t cu_mask_size;
+	uint32_t count;
+	uint32_t *cu_mask = NULL;
+	int ret = 0;
+
+	if (!queue || !props || !compute_mqd)
+		return -EINVAL;
+
+	if (compute_mqd->queue_percentage > AMDGPU_USERQ_MAX_QUEUE_PERCENTAGE) {
+		DRM_ERROR("Queue percentage must be between 0 to AMDGPU_USERQ_MAX_QUEUE_PERCENTAGE.\n");
+		return -EINVAL;
+	}
+
+	/* Validate priority */
+	if (compute_mqd->hqd_queue_priority > AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM) {
+		DRM_ERROR("Queue priority must be between 0 to AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM.\n");
+		return -EINVAL;
+	}
+
+
+	/* validate and set CU mask property */
+	if (compute_mqd->cu_mask_count) {
+		if (compute_mqd->cu_mask_count % 32 != 0) {
+			DRM_ERROR("CU mask count must be a multiple of 32.\n");
+			return -EINVAL;
+		}
+		count = compute_mqd->cu_mask_count;
+
+		/* Limit CU mask size to prevent excessive memory allocation */
+		if (count > max_num_cus) {
+			DRM_ERROR("CU mask cannot be greater than 1024 bits.\n");
+			count = max_num_cus;
+			cu_mask_size = sizeof(uint32_t) * (max_num_cus / 32);
+		} else {
+			cu_mask_size = sizeof(uint32_t) * (compute_mqd->cu_mask_count / 32);
+		}
+
+		/* Copy CU mask from user space */
+		cu_mask = memdup_user(u64_to_user_ptr(compute_mqd->cu_mask_ptr), cu_mask_size);
+		if (IS_ERR(cu_mask)) {
+			ret = PTR_ERR(cu_mask);
+			cu_mask = NULL;
+			goto cleanup;
+		}
+
+		/* Validate pairwise CU mask for WGP-based ASICs */
+		if (cu_mask && adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 0, 0)) {
+			for (int i = 0; i < count; i += 2) {
+			       uint32_t cu_pair = (cu_mask[i / 32] >> (i % 32)) & 0x3;
+			       if (cu_pair && cu_pair != 0x3) {
+				       DRM_ERROR("CUs must be adjacent pairwise enabled.\n");
+				       kfree(cu_mask);
+				       cu_mask = NULL;
+				       ret = -EINVAL;
+				       goto cleanup;
+			       }
+			}
+		}
+
+		/* Free old CU mask */
+		if (props->cu_mask) {
+			kfree(props->cu_mask);
+			props->cu_mask = NULL;
+		}
+
+		props->cu_mask = cu_mask;
+		props->cu_mask_count = count;
+		props->is_user_cu_masked = (cu_mask != NULL);
+	}
+
+	/* Parse HQD priority and other compute properties */
+	props->queue_percentage = compute_mqd->queue_percentage;
+	props->pm4_target_xcc = compute_mqd->pm4_target_xcc;
+	props->hqd_queue_priority = compute_mqd->hqd_queue_priority;
+	props->hqd_pipe_priority = amdgpu_userq_pipe_priority_map[compute_mqd->hqd_queue_priority];
+	props->eop_gpu_addr = compute_mqd->eop_va;
+
+cleanup:
+	return ret;
+}
+
 static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
 				struct drm_amdgpu_userq_in *args_in)
 {
@@ -325,10 +444,10 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
 						   2048);
 		if (r)
 			goto free_mqd;
+		r = amdgpu_userq_set_compute_mqd(queue, userq_props, compute_mqd);
+		if (r)
+			goto free_mqd;
 
-		userq_props->eop_gpu_addr = compute_mqd->eop_va;
-		userq_props->hqd_pipe_priority = AMDGPU_GFX_PIPE_PRIO_NORMAL;
-		userq_props->hqd_queue_priority = AMDGPU_GFX_QUEUE_PRIORITY_MINIMUM;
 		userq_props->hqd_active = false;
 		userq_props->tmz_queue =
 			mqd_user->flags & AMDGPU_USERQ_CREATE_FLAGS_QUEUE_SECURE;
@@ -432,11 +551,51 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
 	return r;
 }
 
+static int mes_userq_mqd_update(struct amdgpu_usermode_queue *queue, struct drm_amdgpu_userq_in *args_in)
+{
+	int retval = 0;
+	struct amdgpu_device *adev = queue->userq_mgr->adev;
+	struct amdgpu_mqd_prop *userq_props = queue->userq_prop;
+	struct amdgpu_mqd *mqd_hw_default = &adev->mqds[queue->queue_type];
+	struct drm_amdgpu_userq_mqd_compute_gfx11 *compute_mqd_v11;
+
+	if (!queue || !userq_props)
+		return -EINVAL;
+
+	if (queue->queue_type != AMDGPU_HW_IP_COMPUTE)
+		return -EINVAL;
+
+	if (args_in->mqd_size != sizeof(*compute_mqd_v11)) {
+		DRM_ERROR("Invalid compute IP MQD size\n");
+		return -EINVAL;
+	}
+
+	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");
+		return -ENOMEM;
+	}
+
+	retval = amdgpu_userq_set_compute_mqd(queue, userq_props, compute_mqd_v11);
+	if (retval)
+		goto free;
+
+	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);
+
+free:
+	kfree(compute_mqd_v11);
+	return retval;
+}
+
 static void mes_userq_mqd_destroy(struct amdgpu_usermode_queue *queue)
 {
 	struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
 
 	amdgpu_userq_destroy_object(uq_mgr, &queue->fw_obj);
+	kfree(queue->userq_prop->cu_mask);
 	kfree(queue->userq_prop);
 	amdgpu_userq_destroy_object(uq_mgr, &queue->mqd);
 }
@@ -513,6 +672,7 @@ static int mes_userq_restore(struct amdgpu_usermode_queue *queue)
 
 const struct amdgpu_userq_funcs userq_mes_funcs = {
 	.mqd_create = mes_userq_mqd_create,
+	.mqd_update = mes_userq_mqd_update,
 	.mqd_destroy = mes_userq_mqd_destroy,
 	.unmap = mes_userq_unmap,
 	.map = mes_userq_map,
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index ab2bf47553e1..c52949ea8c1e 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -341,6 +341,7 @@ union drm_amdgpu_ctx {
 #define AMDGPU_USERQ_CREATE_FLAGS_QUEUE_PRIORITY_HIGH 3 /* admin only */
 /* for queues that need access to protected content */
 #define AMDGPU_USERQ_CREATE_FLAGS_QUEUE_SECURE  (1 << 2)
+#define AMDGPU_USERQ_MAX_QUEUE_PERCENTAGE	100
 
 /*
  * This structure is a container to pass input configuration
@@ -460,6 +461,33 @@ struct drm_amdgpu_userq_mqd_compute_gfx11 {
 	 * to get the size.
 	 */
 	__u64   eop_va;
+       /**
+        * @cu_mask_ptr: User-space pointer to CU (Compute Unit) mask array
+        * Points to an array of __u32 values that define which CUs are enabled
+        * for this queue (0 = disabled, 1 = enabled per bit)
+        */
+       __u64 cu_mask_ptr;
+       /**
+        * @cu_mask_count: Number of entries in the CU mask array
+        * Total count of __u32 elements in the cu_mask_ptr array (each element
+        * represents 32 CUs/WGPs)
+        */
+       __u32 cu_mask_count;
+       /**
+        * @queue_percentage: Queue resource allocation percentage (0-100)
+        * Defines the percentage of GPU resources allocated to this queue
+        */
+       __u32 queue_percentage;
+       /**
+        * @hqd_queue_priority: Hqd Queue priority (0-15)
+        * Higher values indicate higher scheduling priority for the queue
+        */
+       __u32 hqd_queue_priority;
+       /**
+        * @pm4_target_xcc: PM4 target XCC identifier (for gfx9/gfx12.1)
+        * Specifies the target XCC (Cross Compute Complex) for PM4 commands
+        */
+       __u32 pm4_target_xcc;
 };
 
 /* userq signal/wait ioctl */
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 6/6] drm/amdgpu: add MODIFY operation for compute queues
  2026-01-28 10:58 [PATCH v4 1/6] drm/amdgpu: add mqd_update callback to AMDGPU user queue interface Jesse.Zhang
                   ` (3 preceding siblings ...)
  2026-01-28 10:58 ` [PATCH v4 5/6] drm/amdgpu: add MQD update support for user mode compute queues Jesse.Zhang
@ 2026-01-28 10:58 ` Jesse.Zhang
  2026-01-30  8:30   ` Zhang, Jesse(Jie)
                     ` (2 more replies)
  4 siblings, 3 replies; 10+ messages in thread
From: Jesse.Zhang @ 2026-01-28 10:58 UTC (permalink / raw)
  To: amd-gfx
  Cc: Alexander.Deucher, Christian Koenig, Jesse.Zhang, Alex Deucher,
	Jesse Zhang

Implement the AMDGPU_USERQ_OP_MODIFY ioctl operation to enable runtime updates
of compute queues.

v2: move queue size validate to a separate patch
    remove the check for AMDGPU_HW_IP_COMPUTE  (Alex)

Suggested-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 61 +++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h |  3 ++
 include/uapi/drm/amdgpu_drm.h             |  1 +
 3 files changed, 65 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index 256ceca6d429..3003aba22e1d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -837,6 +837,7 @@ static int amdgpu_userq_input_args_validate(struct drm_device *dev,
 
 	switch (args->in.op) {
 	case AMDGPU_USERQ_OP_CREATE:
+	case AMDGPU_USERQ_OP_MODIFY:
 		if (args->in.flags & ~(AMDGPU_USERQ_CREATE_FLAGS_QUEUE_PRIORITY_MASK |
 				       AMDGPU_USERQ_CREATE_FLAGS_QUEUE_SECURE))
 			return -EINVAL;
@@ -901,6 +902,60 @@ bool amdgpu_userq_enabled(struct drm_device *dev)
 	return false;
 }
 
+static int amdgpu_modify_queue(struct drm_file *filp, union drm_amdgpu_userq *args)
+{
+	struct amdgpu_fpriv *fpriv = filp->driver_priv;
+	struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
+	struct amdgpu_device *adev = uq_mgr->adev;
+	struct amdgpu_usermode_queue *queue;
+	const struct amdgpu_userq_funcs *userq_funcs;
+	int r;
+
+	mutex_lock(&uq_mgr->userq_mutex);
+	queue = amdgpu_userq_find(uq_mgr, args->in.queue_id);
+	if (!queue) {
+		drm_file_err(uq_mgr->file, "Queue %u not found\n", args->in.queue_id);
+		r = -EINVAL;
+		goto unlock;
+	}
+
+	userq_funcs = adev->userq_funcs[queue->queue_type];
+
+	/*
+	 * Unmap the queue if it's mapped or preempted to ensure a clean update.
+	 * If the queue is already unmapped or hung, we skip this step.
+	 */
+	if (queue->state == AMDGPU_USERQ_STATE_MAPPED ||
+	    queue->state == AMDGPU_USERQ_STATE_PREEMPTED) {
+		r = amdgpu_userq_unmap_helper(queue);
+		if (r) {
+			drm_file_err(uq_mgr->file, "Failed to unmap queue %llu\n",
+					queue->doorbell_index);
+			goto unlock;
+		}
+	}
+
+	r = userq_funcs->mqd_update(queue, &args->in);
+	if (r)
+		goto unlock;
+	/*
+	 * If the queue is considered active (has valid size, address, and percentage),
+	 * we attempt to map it. This effectively starts the queue or restarts it
+	 * if it was previously running.
+	 */
+	if (AMDGPU_USERQ_IS_ACTIVE(queue)) {
+		r = amdgpu_userq_map_helper(queue);
+		if (r)
+			drm_file_err(uq_mgr->file, "Failed to remap queue %llu after update\n",
+				queue->doorbell_index);
+	}
+
+unlock:
+	mutex_unlock(&uq_mgr->userq_mutex);
+
+	return r;
+}
+
 int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
 		       struct drm_file *filp)
 {
@@ -920,6 +975,12 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
 			drm_file_err(filp, "Failed to create usermode queue\n");
 		break;
 
+
+	case AMDGPU_USERQ_OP_MODIFY:
+		r = amdgpu_modify_queue(filp, args);
+		if (r)
+			drm_file_err(filp, "Failed to modify usermode queue\n");
+		break;
 	case AMDGPU_USERQ_OP_FREE:
 		r = amdgpu_userq_destroy(filp, args->in.queue_id);
 		if (r)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
index 833468b58603..7cd1ea94e368 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
@@ -31,6 +31,9 @@
 #define to_ev_fence(f) container_of(f, struct amdgpu_eviction_fence, base)
 #define uq_mgr_to_fpriv(u) container_of(u, struct amdgpu_fpriv, userq_mgr)
 #define work_to_uq_mgr(w, name) container_of(w, struct amdgpu_userq_mgr, name)
+#define AMDGPU_USERQ_IS_ACTIVE(q) ((q)->userq_prop->queue_size > 0 &&  \
+                           (q)->userq_prop->hqd_base_gpu_addr != 0 &&  \
+                           (q)->userq_prop->queue_percentage > 0)
 
 enum amdgpu_userq_state {
 	AMDGPU_USERQ_STATE_UNMAPPED = 0,
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index c52949ea8c1e..aa9b31578c6b 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -330,6 +330,7 @@ union drm_amdgpu_ctx {
 /* user queue IOCTL operations */
 #define AMDGPU_USERQ_OP_CREATE	1
 #define AMDGPU_USERQ_OP_FREE	2
+#define AMDGPU_USERQ_OP_MODIFY 3
 
 /* queue priority levels */
 /* low < normal low < normal high < high */
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* RE: [PATCH v4 6/6] drm/amdgpu: add MODIFY operation for compute queues
  2026-01-28 10:58 ` [PATCH v4 6/6] drm/amdgpu: add MODIFY operation for " Jesse.Zhang
@ 2026-01-30  8:30   ` Zhang, Jesse(Jie)
  2026-02-02 23:33   ` Zhang, Jesse(Jie)
  2026-02-03 14:06   ` Alex Deucher
  2 siblings, 0 replies; 10+ messages in thread
From: Zhang, Jesse(Jie) @ 2026-01-30  8:30 UTC (permalink / raw)
  To: Zhang, Jesse(Jie), amd-gfx@lists.freedesktop.org
  Cc: Deucher, Alexander, Koenig, Christian, Deucher, Alexander

[AMD Official Use Only - AMD Internal Distribution Only]

Ping ...

> -----Original Message-----
> From: Jesse.Zhang <Jesse.Zhang@amd.com>
> Sent: Wednesday, January 28, 2026 6:58 PM
> To: amd-gfx@lists.freedesktop.org
> Cc: Deucher, Alexander <Alexander.Deucher@amd.com>; Koenig, Christian
> <Christian.Koenig@amd.com>; Zhang, Jesse(Jie) <Jesse.Zhang@amd.com>;
> Deucher, Alexander <Alexander.Deucher@amd.com>; Zhang, Jesse(Jie)
> <Jesse.Zhang@amd.com>
> Subject: [PATCH v4 6/6] drm/amdgpu: add MODIFY operation for compute queues
>
> Implement the AMDGPU_USERQ_OP_MODIFY ioctl operation to enable runtime
> updates of compute queues.
>
> v2: move queue size validate to a separate patch
>     remove the check for AMDGPU_HW_IP_COMPUTE  (Alex)
>
> Suggested-by: Alex Deucher <alexander.deucher@amd.com>
> Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 61
> +++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h |  3
> ++
>  include/uapi/drm/amdgpu_drm.h             |  1 +
>  3 files changed, 65 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> index 256ceca6d429..3003aba22e1d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> @@ -837,6 +837,7 @@ static int amdgpu_userq_input_args_validate(struct
> drm_device *dev,
>
>       switch (args->in.op) {
>       case AMDGPU_USERQ_OP_CREATE:
> +     case AMDGPU_USERQ_OP_MODIFY:
>               if (args->in.flags &
> ~(AMDGPU_USERQ_CREATE_FLAGS_QUEUE_PRIORITY_MASK |
>
> AMDGPU_USERQ_CREATE_FLAGS_QUEUE_SECURE))
>                       return -EINVAL;
> @@ -901,6 +902,60 @@ bool amdgpu_userq_enabled(struct drm_device *dev)
>       return false;
>  }
>
> +static int amdgpu_modify_queue(struct drm_file *filp, union
> +drm_amdgpu_userq *args) {
> +     struct amdgpu_fpriv *fpriv = filp->driver_priv;
> +     struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
> +     struct amdgpu_device *adev = uq_mgr->adev;
> +     struct amdgpu_usermode_queue *queue;
> +     const struct amdgpu_userq_funcs *userq_funcs;
> +     int r;
> +
> +     mutex_lock(&uq_mgr->userq_mutex);
> +     queue = amdgpu_userq_find(uq_mgr, args->in.queue_id);
> +     if (!queue) {
> +             drm_file_err(uq_mgr->file, "Queue %u not found\n", args-
> >in.queue_id);
> +             r = -EINVAL;
> +             goto unlock;
> +     }
> +
> +     userq_funcs = adev->userq_funcs[queue->queue_type];
> +
> +     /*
> +      * Unmap the queue if it's mapped or preempted to ensure a clean update.
> +      * If the queue is already unmapped or hung, we skip this step.
> +      */
> +     if (queue->state == AMDGPU_USERQ_STATE_MAPPED ||
> +         queue->state == AMDGPU_USERQ_STATE_PREEMPTED) {
> +             r = amdgpu_userq_unmap_helper(queue);
> +             if (r) {
> +                     drm_file_err(uq_mgr->file, "Failed to unmap queue %llu\n",
> +                                     queue->doorbell_index);
> +                     goto unlock;
> +             }
> +     }
> +
> +     r = userq_funcs->mqd_update(queue, &args->in);
> +     if (r)
> +             goto unlock;
> +     /*
> +      * If the queue is considered active (has valid size, address, and
> percentage),
> +      * we attempt to map it. This effectively starts the queue or restarts it
> +      * if it was previously running.
> +      */
> +     if (AMDGPU_USERQ_IS_ACTIVE(queue)) {
> +             r = amdgpu_userq_map_helper(queue);
> +             if (r)
> +                     drm_file_err(uq_mgr->file, "Failed to remap queue %llu after
> update\n",
> +                             queue->doorbell_index);
> +     }
> +
> +unlock:
> +     mutex_unlock(&uq_mgr->userq_mutex);
> +
> +     return r;
> +}
> +
>  int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
>                      struct drm_file *filp)
>  {
> @@ -920,6 +975,12 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void
> *data,
>                       drm_file_err(filp, "Failed to create usermode queue\n");
>               break;
>
> +
> +     case AMDGPU_USERQ_OP_MODIFY:
> +             r = amdgpu_modify_queue(filp, args);
> +             if (r)
> +                     drm_file_err(filp, "Failed to modify usermode queue\n");
> +             break;
>       case AMDGPU_USERQ_OP_FREE:
>               r = amdgpu_userq_destroy(filp, args->in.queue_id);
>               if (r)
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> index 833468b58603..7cd1ea94e368 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> @@ -31,6 +31,9 @@
>  #define to_ev_fence(f) container_of(f, struct amdgpu_eviction_fence, base)
> #define uq_mgr_to_fpriv(u) container_of(u, struct amdgpu_fpriv, userq_mgr)
> #define work_to_uq_mgr(w, name) container_of(w, struct amdgpu_userq_mgr,
> name)
> +#define AMDGPU_USERQ_IS_ACTIVE(q) ((q)->userq_prop->queue_size > 0 &&
> \
> +                           (q)->userq_prop->hqd_base_gpu_addr != 0 &&  \
> +                           (q)->userq_prop->queue_percentage > 0)
>
>  enum amdgpu_userq_state {
>       AMDGPU_USERQ_STATE_UNMAPPED = 0,
> diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index
> c52949ea8c1e..aa9b31578c6b 100644
> --- a/include/uapi/drm/amdgpu_drm.h
> +++ b/include/uapi/drm/amdgpu_drm.h
> @@ -330,6 +330,7 @@ union drm_amdgpu_ctx {
>  /* user queue IOCTL operations */
>  #define AMDGPU_USERQ_OP_CREATE       1
>  #define AMDGPU_USERQ_OP_FREE 2
> +#define AMDGPU_USERQ_OP_MODIFY 3
>
>  /* queue priority levels */
>  /* low < normal low < normal high < high */
> --
> 2.49.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH v4 6/6] drm/amdgpu: add MODIFY operation for compute queues
  2026-01-28 10:58 ` [PATCH v4 6/6] drm/amdgpu: add MODIFY operation for " Jesse.Zhang
  2026-01-30  8:30   ` Zhang, Jesse(Jie)
@ 2026-02-02 23:33   ` Zhang, Jesse(Jie)
  2026-02-03 14:06   ` Alex Deucher
  2 siblings, 0 replies; 10+ messages in thread
From: Zhang, Jesse(Jie) @ 2026-02-02 23:33 UTC (permalink / raw)
  To: Zhang, Jesse(Jie), amd-gfx@lists.freedesktop.org
  Cc: Deucher, Alexander, Koenig, Christian, Deucher, Alexander

[AMD Official Use Only - AMD Internal Distribution Only]

Ping...

> -----Original Message-----
> From: Jesse.Zhang <Jesse.Zhang@amd.com>
> Sent: Wednesday, January 28, 2026 6:58 PM
> To: amd-gfx@lists.freedesktop.org
> Cc: Deucher, Alexander <Alexander.Deucher@amd.com>; Koenig, Christian
> <Christian.Koenig@amd.com>; Zhang, Jesse(Jie) <Jesse.Zhang@amd.com>;
> Deucher, Alexander <Alexander.Deucher@amd.com>; Zhang, Jesse(Jie)
> <Jesse.Zhang@amd.com>
> Subject: [PATCH v4 6/6] drm/amdgpu: add MODIFY operation for compute queues
>
> Implement the AMDGPU_USERQ_OP_MODIFY ioctl operation to enable runtime
> updates of compute queues.
>
> v2: move queue size validate to a separate patch
>     remove the check for AMDGPU_HW_IP_COMPUTE  (Alex)
>
> Suggested-by: Alex Deucher <alexander.deucher@amd.com>
> Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 61
> +++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h |  3
> ++
>  include/uapi/drm/amdgpu_drm.h             |  1 +
>  3 files changed, 65 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> index 256ceca6d429..3003aba22e1d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> @@ -837,6 +837,7 @@ static int amdgpu_userq_input_args_validate(struct
> drm_device *dev,
>
>       switch (args->in.op) {
>       case AMDGPU_USERQ_OP_CREATE:
> +     case AMDGPU_USERQ_OP_MODIFY:
>               if (args->in.flags &
> ~(AMDGPU_USERQ_CREATE_FLAGS_QUEUE_PRIORITY_MASK |
>
> AMDGPU_USERQ_CREATE_FLAGS_QUEUE_SECURE))
>                       return -EINVAL;
> @@ -901,6 +902,60 @@ bool amdgpu_userq_enabled(struct drm_device *dev)
>       return false;
>  }
>
> +static int amdgpu_modify_queue(struct drm_file *filp, union
> +drm_amdgpu_userq *args) {
> +     struct amdgpu_fpriv *fpriv = filp->driver_priv;
> +     struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
> +     struct amdgpu_device *adev = uq_mgr->adev;
> +     struct amdgpu_usermode_queue *queue;
> +     const struct amdgpu_userq_funcs *userq_funcs;
> +     int r;
> +
> +     mutex_lock(&uq_mgr->userq_mutex);
> +     queue = amdgpu_userq_find(uq_mgr, args->in.queue_id);
> +     if (!queue) {
> +             drm_file_err(uq_mgr->file, "Queue %u not found\n", args-
> >in.queue_id);
> +             r = -EINVAL;
> +             goto unlock;
> +     }
> +
> +     userq_funcs = adev->userq_funcs[queue->queue_type];
> +
> +     /*
> +      * Unmap the queue if it's mapped or preempted to ensure a clean update.
> +      * If the queue is already unmapped or hung, we skip this step.
> +      */
> +     if (queue->state == AMDGPU_USERQ_STATE_MAPPED ||
> +         queue->state == AMDGPU_USERQ_STATE_PREEMPTED) {
> +             r = amdgpu_userq_unmap_helper(queue);
> +             if (r) {
> +                     drm_file_err(uq_mgr->file, "Failed to unmap queue %llu\n",
> +                                     queue->doorbell_index);
> +                     goto unlock;
> +             }
> +     }
> +
> +     r = userq_funcs->mqd_update(queue, &args->in);
> +     if (r)
> +             goto unlock;
> +     /*
> +      * If the queue is considered active (has valid size, address, and
> percentage),
> +      * we attempt to map it. This effectively starts the queue or restarts it
> +      * if it was previously running.
> +      */
> +     if (AMDGPU_USERQ_IS_ACTIVE(queue)) {
> +             r = amdgpu_userq_map_helper(queue);
> +             if (r)
> +                     drm_file_err(uq_mgr->file, "Failed to remap queue %llu after
> update\n",
> +                             queue->doorbell_index);
> +     }
> +
> +unlock:
> +     mutex_unlock(&uq_mgr->userq_mutex);
> +
> +     return r;
> +}
> +
>  int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
>                      struct drm_file *filp)
>  {
> @@ -920,6 +975,12 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void
> *data,
>                       drm_file_err(filp, "Failed to create usermode queue\n");
>               break;
>
> +
> +     case AMDGPU_USERQ_OP_MODIFY:
> +             r = amdgpu_modify_queue(filp, args);
> +             if (r)
> +                     drm_file_err(filp, "Failed to modify usermode queue\n");
> +             break;
>       case AMDGPU_USERQ_OP_FREE:
>               r = amdgpu_userq_destroy(filp, args->in.queue_id);
>               if (r)
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> index 833468b58603..7cd1ea94e368 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> @@ -31,6 +31,9 @@
>  #define to_ev_fence(f) container_of(f, struct amdgpu_eviction_fence, base)
> #define uq_mgr_to_fpriv(u) container_of(u, struct amdgpu_fpriv, userq_mgr)
> #define work_to_uq_mgr(w, name) container_of(w, struct amdgpu_userq_mgr,
> name)
> +#define AMDGPU_USERQ_IS_ACTIVE(q) ((q)->userq_prop->queue_size > 0 &&
> \
> +                           (q)->userq_prop->hqd_base_gpu_addr != 0 &&  \
> +                           (q)->userq_prop->queue_percentage > 0)
>
>  enum amdgpu_userq_state {
>       AMDGPU_USERQ_STATE_UNMAPPED = 0,
> diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index
> c52949ea8c1e..aa9b31578c6b 100644
> --- a/include/uapi/drm/amdgpu_drm.h
> +++ b/include/uapi/drm/amdgpu_drm.h
> @@ -330,6 +330,7 @@ union drm_amdgpu_ctx {
>  /* user queue IOCTL operations */
>  #define AMDGPU_USERQ_OP_CREATE       1
>  #define AMDGPU_USERQ_OP_FREE 2
> +#define AMDGPU_USERQ_OP_MODIFY 3
>
>  /* queue priority levels */
>  /* low < normal low < normal high < high */
> --
> 2.49.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 6/6] drm/amdgpu: add MODIFY operation for compute queues
  2026-01-28 10:58 ` [PATCH v4 6/6] drm/amdgpu: add MODIFY operation for " Jesse.Zhang
  2026-01-30  8:30   ` Zhang, Jesse(Jie)
  2026-02-02 23:33   ` Zhang, Jesse(Jie)
@ 2026-02-03 14:06   ` Alex Deucher
  2 siblings, 0 replies; 10+ messages in thread
From: Alex Deucher @ 2026-02-03 14:06 UTC (permalink / raw)
  To: Jesse.Zhang; +Cc: amd-gfx, Alexander.Deucher, Christian Koenig

On Wed, Jan 28, 2026 at 6:07 AM Jesse.Zhang <Jesse.Zhang@amd.com> wrote:
>
> Implement the AMDGPU_USERQ_OP_MODIFY ioctl operation to enable runtime updates
> of compute queues.
>
> v2: move queue size validate to a separate patch
>     remove the check for AMDGPU_HW_IP_COMPUTE  (Alex)
>
> Suggested-by: Alex Deucher <alexander.deucher@amd.com>
> Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 61 +++++++++++++++++++++++
>  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h |  3 ++
>  include/uapi/drm/amdgpu_drm.h             |  1 +
>  3 files changed, 65 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> index 256ceca6d429..3003aba22e1d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> @@ -837,6 +837,7 @@ static int amdgpu_userq_input_args_validate(struct drm_device *dev,
>
>         switch (args->in.op) {
>         case AMDGPU_USERQ_OP_CREATE:
> +       case AMDGPU_USERQ_OP_MODIFY:
>                 if (args->in.flags & ~(AMDGPU_USERQ_CREATE_FLAGS_QUEUE_PRIORITY_MASK |
>                                        AMDGPU_USERQ_CREATE_FLAGS_QUEUE_SECURE))
>                         return -EINVAL;
> @@ -901,6 +902,60 @@ bool amdgpu_userq_enabled(struct drm_device *dev)
>         return false;
>  }
>
> +static int amdgpu_modify_queue(struct drm_file *filp, union drm_amdgpu_userq *args)
> +{
> +       struct amdgpu_fpriv *fpriv = filp->driver_priv;
> +       struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
> +       struct amdgpu_device *adev = uq_mgr->adev;
> +       struct amdgpu_usermode_queue *queue;
> +       const struct amdgpu_userq_funcs *userq_funcs;
> +       int r;
> +
> +       mutex_lock(&uq_mgr->userq_mutex);
> +       queue = amdgpu_userq_find(uq_mgr, args->in.queue_id);
> +       if (!queue) {
> +               drm_file_err(uq_mgr->file, "Queue %u not found\n", args->in.queue_id);
> +               r = -EINVAL;
> +               goto unlock;
> +       }
> +
> +       userq_funcs = adev->userq_funcs[queue->queue_type];
> +
> +       /*
> +        * Unmap the queue if it's mapped or preempted to ensure a clean update.
> +        * If the queue is already unmapped or hung, we skip this step.
> +        */
> +       if (queue->state == AMDGPU_USERQ_STATE_MAPPED ||
> +           queue->state == AMDGPU_USERQ_STATE_PREEMPTED) {
> +               r = amdgpu_userq_unmap_helper(queue);
> +               if (r) {
> +                       drm_file_err(uq_mgr->file, "Failed to unmap queue %llu\n",
> +                                       queue->doorbell_index);
> +                       goto unlock;
> +               }
> +       }
> +
> +       r = userq_funcs->mqd_update(queue, &args->in);
> +       if (r)
> +               goto unlock;
> +       /*
> +        * If the queue is considered active (has valid size, address, and percentage),
> +        * we attempt to map it. This effectively starts the queue or restarts it
> +        * if it was previously running.
> +        */
> +       if (AMDGPU_USERQ_IS_ACTIVE(queue)) {
> +               r = amdgpu_userq_map_helper(queue);
> +               if (r)
> +                       drm_file_err(uq_mgr->file, "Failed to remap queue %llu after update\n",
> +                               queue->doorbell_index);
> +       }
> +
> +unlock:
> +       mutex_unlock(&uq_mgr->userq_mutex);
> +
> +       return r;
> +}
> +
>  int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
>                        struct drm_file *filp)
>  {
> @@ -920,6 +975,12 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
>                         drm_file_err(filp, "Failed to create usermode queue\n");
>                 break;
>
> +
> +       case AMDGPU_USERQ_OP_MODIFY:
> +               r = amdgpu_modify_queue(filp, args);
> +               if (r)
> +                       drm_file_err(filp, "Failed to modify usermode queue\n");
> +               break;
>         case AMDGPU_USERQ_OP_FREE:
>                 r = amdgpu_userq_destroy(filp, args->in.queue_id);
>                 if (r)
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> index 833468b58603..7cd1ea94e368 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> @@ -31,6 +31,9 @@
>  #define to_ev_fence(f) container_of(f, struct amdgpu_eviction_fence, base)
>  #define uq_mgr_to_fpriv(u) container_of(u, struct amdgpu_fpriv, userq_mgr)
>  #define work_to_uq_mgr(w, name) container_of(w, struct amdgpu_userq_mgr, name)
> +#define AMDGPU_USERQ_IS_ACTIVE(q) ((q)->userq_prop->queue_size > 0 &&  \
> +                           (q)->userq_prop->hqd_base_gpu_addr != 0 &&  \
> +                           (q)->userq_prop->queue_percentage > 0)
>
>  enum amdgpu_userq_state {
>         AMDGPU_USERQ_STATE_UNMAPPED = 0,
> diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
> index c52949ea8c1e..aa9b31578c6b 100644
> --- a/include/uapi/drm/amdgpu_drm.h
> +++ b/include/uapi/drm/amdgpu_drm.h
> @@ -330,6 +330,7 @@ union drm_amdgpu_ctx {
>  /* user queue IOCTL operations */
>  #define AMDGPU_USERQ_OP_CREATE 1
>  #define AMDGPU_USERQ_OP_FREE   2
> +#define AMDGPU_USERQ_OP_MODIFY 3
>
>  /* queue priority levels */
>  /* low < normal low < normal high < high */
> --
> 2.49.0
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 5/6] drm/amdgpu: add MQD update support for user mode compute queues
  2026-01-28 10:58 ` [PATCH v4 5/6] drm/amdgpu: add MQD update support for user mode compute queues Jesse.Zhang
@ 2026-02-03 14:22   ` Lazar, Lijo
  0 siblings, 0 replies; 10+ messages in thread
From: Lazar, Lijo @ 2026-02-03 14:22 UTC (permalink / raw)
  To: Jesse.Zhang, amd-gfx; +Cc: Alexander.Deucher, Christian Koenig



On 28-Jan-26 4:28 PM, Jesse.Zhang wrote:
> The update functionality allows dynamic adjustment of queue properties at runtime,
> enabling better resource management and performance tuning for compute workloads.
> 
> v2: Return an error for non-compute queues. (Alex)
>      remove the parameter minfo
> 
> V3: put the new paramters in drm_amdgpu_userq_mqd_compute_gfx11. (Alex)
> v4: move the define AMDGPU_USERQ_OP_MODIFY to patch 6/6 (Alex)
>      add the props input paramter to amdgpu_userq_set_compute_mqd
> 
> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
> Suggested-by: Alex Deucher <alexander.deucher@amd.com>
> Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu.h        |   3 +
>   drivers/gpu/drm/amd/amdgpu/mes_userqueue.c | 166 ++++++++++++++++++++-
>   include/uapi/drm/amdgpu_drm.h              |  28 ++++
>   3 files changed, 194 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index a8f4f73fa0ce..ad136145316b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -819,6 +819,9 @@ struct amdgpu_mqd_prop {
>   	uint32_t cu_mask_count;
>   	uint32_t cu_flags;
>   	bool is_user_cu_masked;
> +	uint32_t queue_percentage;

This field is not implemented in KFD itself apart from active/inactive. 
Should this be kept in the same way?

Thanks,
Lijo

> +	/* used in gfx9 and gfx12.1 */
> +	uint32_t pm4_target_xcc;
>   };
>   
>   struct amdgpu_mqd {
> diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
> index f2309d72bbe6..d5251f2d7613 100644
> --- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
> +++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
> @@ -30,6 +30,26 @@
>   #define AMDGPU_USERQ_PROC_CTX_SZ PAGE_SIZE
>   #define AMDGPU_USERQ_GANG_CTX_SZ PAGE_SIZE
>   
> +/* Mapping queue priority to pipe priority, indexed by queue priority */
> +int amdgpu_userq_pipe_priority_map[] = {
> +	AMDGPU_RING_PRIO_0,
> +	AMDGPU_RING_PRIO_0,
> +	AMDGPU_RING_PRIO_0,
> +	AMDGPU_RING_PRIO_0,
> +	AMDGPU_RING_PRIO_0,
> +	AMDGPU_RING_PRIO_0,
> +	AMDGPU_RING_PRIO_0,
> +	AMDGPU_RING_PRIO_1,
> +	AMDGPU_RING_PRIO_1,
> +	AMDGPU_RING_PRIO_1,
> +	AMDGPU_RING_PRIO_1,
> +	AMDGPU_RING_PRIO_2,
> +	AMDGPU_RING_PRIO_2,
> +	AMDGPU_RING_PRIO_2,
> +	AMDGPU_RING_PRIO_2,
> +	AMDGPU_RING_PRIO_2
> +};
> +
>   static int
>   mes_userq_map_gtt_bo_to_gart(struct amdgpu_bo *bo)
>   {
> @@ -272,6 +292,105 @@ static int mes_userq_detect_and_reset(struct amdgpu_device *adev,
>   	return r;
>   }
>   
> +/**
> + * amdgpu_userq_set_compute_mqd - Parse compute MQD and update queue props
> + * @queue: Target user mode queue
> + * @props: Queue property structure to be updated
> + * @args: User queue input arguments
> + * @uq_mgr: User queue manager (for logging)
> + *
> + * This function only parses and validates user input, updating queue props
> + * (no hardware MQD configuration - that's handled in MES layer)
> + * Returns: 0 on success, negative error code on failure
> + */
> +static int amdgpu_userq_set_compute_mqd(struct amdgpu_usermode_queue *queue,
> +					struct amdgpu_mqd_prop *props,
> +					struct drm_amdgpu_userq_mqd_compute_gfx11 * compute_mqd)
> +{
> +	struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
> +	struct amdgpu_device *adev = uq_mgr->adev;
> +	const int max_num_cus = 1024;
> +	size_t cu_mask_size;
> +	uint32_t count;
> +	uint32_t *cu_mask = NULL;
> +	int ret = 0;
> +
> +	if (!queue || !props || !compute_mqd)
> +		return -EINVAL;
> +
> +	if (compute_mqd->queue_percentage > AMDGPU_USERQ_MAX_QUEUE_PERCENTAGE) {
> +		DRM_ERROR("Queue percentage must be between 0 to AMDGPU_USERQ_MAX_QUEUE_PERCENTAGE.\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Validate priority */
> +	if (compute_mqd->hqd_queue_priority > AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM) {
> +		DRM_ERROR("Queue priority must be between 0 to AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM.\n");
> +		return -EINVAL;
> +	}
> +
> +
> +	/* validate and set CU mask property */
> +	if (compute_mqd->cu_mask_count) {
> +		if (compute_mqd->cu_mask_count % 32 != 0) {
> +			DRM_ERROR("CU mask count must be a multiple of 32.\n");
> +			return -EINVAL;
> +		}
> +		count = compute_mqd->cu_mask_count;
> +
> +		/* Limit CU mask size to prevent excessive memory allocation */
> +		if (count > max_num_cus) {
> +			DRM_ERROR("CU mask cannot be greater than 1024 bits.\n");
> +			count = max_num_cus;
> +			cu_mask_size = sizeof(uint32_t) * (max_num_cus / 32);
> +		} else {
> +			cu_mask_size = sizeof(uint32_t) * (compute_mqd->cu_mask_count / 32);
> +		}
> +
> +		/* Copy CU mask from user space */
> +		cu_mask = memdup_user(u64_to_user_ptr(compute_mqd->cu_mask_ptr), cu_mask_size);
> +		if (IS_ERR(cu_mask)) {
> +			ret = PTR_ERR(cu_mask);
> +			cu_mask = NULL;
> +			goto cleanup;
> +		}
> +
> +		/* Validate pairwise CU mask for WGP-based ASICs */
> +		if (cu_mask && adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 0, 0)) {
> +			for (int i = 0; i < count; i += 2) {
> +			       uint32_t cu_pair = (cu_mask[i / 32] >> (i % 32)) & 0x3;
> +			       if (cu_pair && cu_pair != 0x3) {
> +				       DRM_ERROR("CUs must be adjacent pairwise enabled.\n");
> +				       kfree(cu_mask);
> +				       cu_mask = NULL;
> +				       ret = -EINVAL;
> +				       goto cleanup;
> +			       }
> +			}
> +		}
> +
> +		/* Free old CU mask */
> +		if (props->cu_mask) {
> +			kfree(props->cu_mask);
> +			props->cu_mask = NULL;
> +		}
> +
> +		props->cu_mask = cu_mask;
> +		props->cu_mask_count = count;
> +		props->is_user_cu_masked = (cu_mask != NULL);
> +	}
> +
> +	/* Parse HQD priority and other compute properties */
> +	props->queue_percentage = compute_mqd->queue_percentage;
> +	props->pm4_target_xcc = compute_mqd->pm4_target_xcc;
> +	props->hqd_queue_priority = compute_mqd->hqd_queue_priority;
> +	props->hqd_pipe_priority = amdgpu_userq_pipe_priority_map[compute_mqd->hqd_queue_priority];
> +	props->eop_gpu_addr = compute_mqd->eop_va;
> +
> +cleanup:
> +	return ret;
> +}
> +
>   static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
>   				struct drm_amdgpu_userq_in *args_in)
>   {
> @@ -325,10 +444,10 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
>   						   2048);
>   		if (r)
>   			goto free_mqd;
> +		r = amdgpu_userq_set_compute_mqd(queue, userq_props, compute_mqd);
> +		if (r)
> +			goto free_mqd;
>   
> -		userq_props->eop_gpu_addr = compute_mqd->eop_va;
> -		userq_props->hqd_pipe_priority = AMDGPU_GFX_PIPE_PRIO_NORMAL;
> -		userq_props->hqd_queue_priority = AMDGPU_GFX_QUEUE_PRIORITY_MINIMUM;
>   		userq_props->hqd_active = false;
>   		userq_props->tmz_queue =
>   			mqd_user->flags & AMDGPU_USERQ_CREATE_FLAGS_QUEUE_SECURE;
> @@ -432,11 +551,51 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
>   	return r;
>   }
>   
> +static int mes_userq_mqd_update(struct amdgpu_usermode_queue *queue, struct drm_amdgpu_userq_in *args_in)
> +{
> +	int retval = 0;
> +	struct amdgpu_device *adev = queue->userq_mgr->adev;
> +	struct amdgpu_mqd_prop *userq_props = queue->userq_prop;
> +	struct amdgpu_mqd *mqd_hw_default = &adev->mqds[queue->queue_type];
> +	struct drm_amdgpu_userq_mqd_compute_gfx11 *compute_mqd_v11;
> +
> +	if (!queue || !userq_props)
> +		return -EINVAL;
> +
> +	if (queue->queue_type != AMDGPU_HW_IP_COMPUTE)
> +		return -EINVAL;
> +
> +	if (args_in->mqd_size != sizeof(*compute_mqd_v11)) {
> +		DRM_ERROR("Invalid compute IP MQD size\n");
> +		return -EINVAL;
> +	}
> +
> +	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");
> +		return -ENOMEM;
> +	}
> +
> +	retval = amdgpu_userq_set_compute_mqd(queue, userq_props, compute_mqd_v11);
> +	if (retval)
> +		goto free;
> +
> +	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);
> +
> +free:
> +	kfree(compute_mqd_v11);
> +	return retval;
> +}
> +
>   static void mes_userq_mqd_destroy(struct amdgpu_usermode_queue *queue)
>   {
>   	struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
>   
>   	amdgpu_userq_destroy_object(uq_mgr, &queue->fw_obj);
> +	kfree(queue->userq_prop->cu_mask);
>   	kfree(queue->userq_prop);
>   	amdgpu_userq_destroy_object(uq_mgr, &queue->mqd);
>   }
> @@ -513,6 +672,7 @@ static int mes_userq_restore(struct amdgpu_usermode_queue *queue)
>   
>   const struct amdgpu_userq_funcs userq_mes_funcs = {
>   	.mqd_create = mes_userq_mqd_create,
> +	.mqd_update = mes_userq_mqd_update,
>   	.mqd_destroy = mes_userq_mqd_destroy,
>   	.unmap = mes_userq_unmap,
>   	.map = mes_userq_map,
> diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
> index ab2bf47553e1..c52949ea8c1e 100644
> --- a/include/uapi/drm/amdgpu_drm.h
> +++ b/include/uapi/drm/amdgpu_drm.h
> @@ -341,6 +341,7 @@ union drm_amdgpu_ctx {
>   #define AMDGPU_USERQ_CREATE_FLAGS_QUEUE_PRIORITY_HIGH 3 /* admin only */
>   /* for queues that need access to protected content */
>   #define AMDGPU_USERQ_CREATE_FLAGS_QUEUE_SECURE  (1 << 2)
> +#define AMDGPU_USERQ_MAX_QUEUE_PERCENTAGE	100
>   
>   /*
>    * This structure is a container to pass input configuration
> @@ -460,6 +461,33 @@ struct drm_amdgpu_userq_mqd_compute_gfx11 {
>   	 * to get the size.
>   	 */
>   	__u64   eop_va;
> +       /**
> +        * @cu_mask_ptr: User-space pointer to CU (Compute Unit) mask array
> +        * Points to an array of __u32 values that define which CUs are enabled
> +        * for this queue (0 = disabled, 1 = enabled per bit)
> +        */
> +       __u64 cu_mask_ptr;
> +       /**
> +        * @cu_mask_count: Number of entries in the CU mask array
> +        * Total count of __u32 elements in the cu_mask_ptr array (each element
> +        * represents 32 CUs/WGPs)
> +        */
> +       __u32 cu_mask_count;
> +       /**
> +        * @queue_percentage: Queue resource allocation percentage (0-100)
> +        * Defines the percentage of GPU resources allocated to this queue
> +        */
> +       __u32 queue_percentage;
> +       /**
> +        * @hqd_queue_priority: Hqd Queue priority (0-15)
> +        * Higher values indicate higher scheduling priority for the queue
> +        */
> +       __u32 hqd_queue_priority;
> +       /**
> +        * @pm4_target_xcc: PM4 target XCC identifier (for gfx9/gfx12.1)
> +        * Specifies the target XCC (Cross Compute Complex) for PM4 commands
> +        */
> +       __u32 pm4_target_xcc;
>   };
>   
>   /* userq signal/wait ioctl */


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-02-03 14:23 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-28 10:58 [PATCH v4 1/6] drm/amdgpu: add mqd_update callback to AMDGPU user queue interface Jesse.Zhang
2026-01-28 10:58 ` [PATCH v4 2/6] drm/amdgpu: Add CU mask support for MQD properties Jesse.Zhang
2026-01-28 10:58 ` [PATCH v4 3/6] drm/amdgpu/gfx11: add CU mask support for compute MQD initialization Jesse.Zhang
2026-01-28 10:58 ` [PATCH v4 4/6] drm/amdgpu/gfx12: " Jesse.Zhang
2026-01-28 10:58 ` [PATCH v4 5/6] drm/amdgpu: add MQD update support for user mode compute queues Jesse.Zhang
2026-02-03 14:22   ` Lazar, Lijo
2026-01-28 10:58 ` [PATCH v4 6/6] drm/amdgpu: add MODIFY operation for " Jesse.Zhang
2026-01-30  8:30   ` Zhang, Jesse(Jie)
2026-02-02 23:33   ` Zhang, Jesse(Jie)
2026-02-03 14:06   ` Alex Deucher

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox