From 1aeddf782e86c6bde353eba122a125518858acb9 Mon Sep 17 00:00:00 2001 From: "Jesse.zhang" Date: Wed, 28 Jan 2026 14:19:19 +0800 Subject: [PATCH 1/2] amdgpu: Add user queue modify support and extend MQD structure The modify functionality enables dynamic queue reconfiguration at runtime, allowing adjustment of compute resources, priorities, and target hardware without requiring queue destruction/recreation. kernel patch: https://lists.freedesktop.org/archives/amd-gfx/2026-January/137519.html Signed-off-by: Jesse Zhang --- amdgpu/amdgpu-symbols.txt | 1 + amdgpu/amdgpu.h | 22 +++++++++++++++++ amdgpu/amdgpu_userq.c | 51 +++++++++++++++++++++++++++++++++++++++ include/drm/amdgpu_drm.h | 28 +++++++++++++++++++++ 4 files changed, 102 insertions(+) diff --git a/amdgpu/amdgpu-symbols.txt b/amdgpu/amdgpu-symbols.txt index 8cd5559c..66147349 100644 --- a/amdgpu/amdgpu-symbols.txt +++ b/amdgpu/amdgpu-symbols.txt @@ -85,6 +85,7 @@ amdgpu_va_range_query amdgpu_vm_reserve_vmid amdgpu_vm_unreserve_vmid amdgpu_create_userqueue +amdgpu_modify_userqueue amdgpu_free_userqueue amdgpu_userq_signal amdgpu_userq_wait diff --git a/amdgpu/amdgpu.h b/amdgpu/amdgpu.h index 6fb2b60b..60cd43cb 100644 --- a/amdgpu/amdgpu.h +++ b/amdgpu/amdgpu.h @@ -2029,6 +2029,28 @@ int amdgpu_create_userqueue(amdgpu_device_handle dev, uint32_t flags, uint32_t *queue_id); +/** + * Modify USERQUEUE + * \param dev - \c [in] device handle + * \param ip_type - \c [in] ip type + * \param queue_id - \c [in] queue id + * \param queue_va - \c [in] Virtual address of queue + * \param queue_size - \c [in] userqueue size + * \param wptr_va - \c [in] Virtual address of wptr + * \param rptr_va - \c [in] Virtual address of rptr + * \param mqd_in - \c [in] MQD data + * + * \return 0 on success otherwise POSIX Error code + */ +int amdgpu_modify_userqueue(amdgpu_device_handle dev, + uint32_t ip_type, + uint32_t queue_id, + uint64_t queue_va, + uint64_t queue_size, + uint64_t wptr_va, + uint64_t rptr_va, + void *mqd_in); + /** * Free USERQUEUE * \param dev - \c [in] device handle diff --git a/amdgpu/amdgpu_userq.c b/amdgpu/amdgpu_userq.c index 123c979e..804c72d2 100644 --- a/amdgpu/amdgpu_userq.c +++ b/amdgpu/amdgpu_userq.c @@ -85,6 +85,57 @@ amdgpu_create_userqueue(amdgpu_device_handle dev, return ret; } +drm_public int +amdgpu_modify_userqueue(amdgpu_device_handle dev, + uint32_t ip_type, + uint32_t queue_id, + uint64_t queue_va, + uint64_t queue_size, + uint64_t wptr_va, + uint64_t rptr_va, + void *mqd_in) +{ + int ret; + union drm_amdgpu_userq userq; + uint64_t mqd_size; + + if (!dev) + return -EINVAL; + + switch (ip_type) { + case AMDGPU_HW_IP_GFX: + mqd_size = sizeof(struct drm_amdgpu_userq_mqd_gfx11); + break; + case AMDGPU_HW_IP_DMA: + mqd_size = sizeof(struct drm_amdgpu_userq_mqd_sdma_gfx11); + break; + case AMDGPU_HW_IP_COMPUTE: + mqd_size = sizeof(struct drm_amdgpu_userq_mqd_compute_gfx11); + break; + default: + return -EINVAL; + } + + memset(&userq, 0, sizeof(userq)); + + userq.in.op = AMDGPU_USERQ_OP_MODIFY; + userq.in.ip_type = ip_type; + userq.in.queue_id = queue_id; + + userq.in.queue_va = queue_va; + userq.in.queue_size = queue_size; + userq.in.wptr_va = wptr_va; + userq.in.rptr_va = rptr_va; + + userq.in.mqd = (uint64_t)mqd_in; + userq.in.mqd_size = mqd_size; + + ret = drmCommandWriteRead(dev->fd, DRM_AMDGPU_USERQ, + &userq, sizeof(userq)); + + return ret; +} + drm_public int amdgpu_free_userqueue(amdgpu_device_handle dev, uint32_t queue_id) { diff --git a/include/drm/amdgpu_drm.h b/include/drm/amdgpu_drm.h index 8db4df39..f7bc9457 100644 --- a/include/drm/amdgpu_drm.h +++ b/include/drm/amdgpu_drm.h @@ -326,6 +326,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 */ #define AMDGPU_USERQ_CREATE_FLAGS_QUEUE_PRIORITY_MASK 0x3 @@ -456,6 +457,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 */ From 01cb0eb121b6c44e1526a715c98c4a2113741b8a Mon Sep 17 00:00:00 2001 From: "Jesse.Zhang" Date: Thu, 29 Jan 2026 15:31:55 +0800 Subject: [PATCH 2/2] drm/amdgpu: Add user queue HQD count to hw_ip info Add a new field userq_num_hqds to drm_amdgpu_info_hw_ip to expose the number of available hardware queue descriptors (HQDs) for user queues. This allows userspace to query the maximum number of user queues that can be created for a particular IP block. the patch link in driver side: https://lists.freedesktop.org/archives/amd-gfx/2025-June/126686.html https://lists.freedesktop.org/archives/amd-gfx/2025-July/126981.html v2: rename userq_num_hqds to userq_num_slots (Marek) Signed-off-by: Jesse Zhang --- include/drm/amdgpu_drm.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/drm/amdgpu_drm.h b/include/drm/amdgpu_drm.h index f7bc9457..ed63e61f 100644 --- a/include/drm/amdgpu_drm.h +++ b/include/drm/amdgpu_drm.h @@ -1512,6 +1512,8 @@ struct drm_amdgpu_info_hw_ip { __u32 available_rings; /** version info: bits 23:16 major, 15:8 minor, 7:0 revision */ __u32 ip_discovery_version; + /* Userq available slots */ + __u32 userq_num_slots; }; /* GFX metadata BO sizes and alignment info (in bytes) */