AMD-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/amdkfd: Enable SDMA queue oversubscription for GFX 12.0.x
@ 2026-08-20 15:36 Sreekant Somasekharan
  2026-08-27 16:27 ` Somasekharan, Sreekant
  2026-08-27 16:39 ` Kuehling, Felix
  0 siblings, 2 replies; 3+ messages in thread
From: Sreekant Somasekharan @ 2026-08-20 15:36 UTC (permalink / raw)
  To: amd-gfx; +Cc: harish.kasiviswanathan, Sreekant Somasekharan

When all HW SDMA slots are exhausted on GFX 12.0.x with MES enabled,
allow new queues to reuse HW queue IDs round-robin via a dedicated
monotonic rotor. Each oversubscribed queue gets a unique doorbell from
the per-process bitmap pool so MES can multiplex them independently.

Normal SDMA queues and all other GPU generations are unaffected.

Assisted-by: Claude:Sonnet 4.6
Signed-off-by: Sreekant Somasekharan <Sreekant.Somasekharan@amd.com>
---
 .../drm/amd/amdkfd/kfd_device_queue_manager.c | 54 +++++++++++++++----
 .../drm/amd/amdkfd/kfd_device_queue_manager.h |  4 ++
 drivers/gpu/drm/amd/amdkfd/kfd_priv.h         |  1 +
 3 files changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index a23384571193..10a672b87ca5 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -556,8 +556,9 @@ static int allocate_doorbell(struct qcm_process_device *qpd,
 			return -EINVAL;
 
 		q->doorbell_id = q->properties.queue_id;
-	} else if (q->properties.type == KFD_QUEUE_TYPE_SDMA ||
-			q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) {
+	} else if ((q->properties.type == KFD_QUEUE_TYPE_SDMA ||
+			q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) &&
+			!q->properties.is_oversubscribed) {
 		/* For SDMA queues on SOC15 with 8-byte doorbell, use static
 		 * doorbell assignments based on the engine and queue id.
 		 * The doobell index distance between RLC (2*i) and (2*i+1)
@@ -583,7 +584,10 @@ static int allocate_doorbell(struct qcm_process_device *qpd,
 			return -EINVAL;
 		q->doorbell_id = valid_id;
 	} else {
-		/* For CP queues on SOC15 */
+		/* For CP queues on SOC15, and oversubscribed SDMA queues which
+		 * reuse HW queue ids and so need a unique doorbell allocated
+		 * from the per-process bitmap pool.
+		 */
 		if (restore_id) {
 			if (*restore_id >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
 				return -EINVAL;
@@ -621,9 +625,14 @@ static void deallocate_doorbell(struct qcm_process_device *qpd,
 	unsigned int old;
 	struct kfd_node *dev = qpd->dqm->dev;
 
+	/* Oversubscribed SDMA queues allocate a doorbell from the bitmap pool
+	 * (like CP queues), so they must be freed; normal SDMA queues use
+	 * static doorbell assignments and must not be.
+	 */
 	if (!KFD_IS_SOC15(dev) ||
-	    q->properties.type == KFD_QUEUE_TYPE_SDMA ||
-	    q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)
+	    ((q->properties.type == KFD_QUEUE_TYPE_SDMA ||
+	      q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) &&
+	     !q->properties.is_oversubscribed))
 		return;
 
 	old = test_and_clear_bit(q->doorbell_id, qpd->doorbell_bitmap);
@@ -1800,15 +1809,33 @@ static int allocate_sdma_queue(struct device_queue_manager *dqm,
 {
 	struct device *dev = dqm->dev->adev->dev;
 	int bit;
+	bool is_oversubscribed = false;
 
 	if (q->properties.type == KFD_QUEUE_TYPE_SDMA) {
 		if (bitmap_empty(dqm->sdma_bitmap, get_num_sdma_queues(dqm))) {
-			dev_warn(dev, "No more SDMA queue to allocate (%d total queues)\n",
-				 get_num_sdma_queues(dqm));
-			return -ENOMEM;
-		}
+			/* All HW queues are busy. On GFX 12.0.x under MES,
+			 * oversubscribe by reusing a HW queue id round-robin;
+			 * MES multiplexes the SW queues via their unique
+			 * doorbells. The non-MES HWS runlist path cannot express
+			 * duplicate sdma_ids, so it still fails with -ENOMEM.
+			 */
+			unsigned int num_reserved, num_available;
+
+			if (KFD_GC_VERSION(dqm->dev) < IP_VERSION(12, 0, 0) ||
+			    KFD_GC_VERSION(dqm->dev) >= IP_VERSION(12, 1, 0) ||
+			    !dqm->dev->kfd->shared_resources.enable_mes) {
+				dev_warn(dev, "No more SDMA queue to allocate (%d total queues)\n",
+					 get_num_sdma_queues(dqm));
+				return -ENOMEM;
+			}
 
-		if (restore_sdma_id) {
+			num_reserved = kfd_get_num_sdma_engines(dqm->dev) *
+				dqm->dev->kfd->device_info.num_reserved_sdma_queues_per_engine;
+			num_available = get_num_sdma_queues(dqm) - num_reserved;
+			q->sdma_id = num_reserved +
+				dqm->sdma_oversub_rotor++ % num_available;
+			is_oversubscribed = true;
+		} else if (restore_sdma_id) {
 			if (*restore_sdma_id >= get_num_sdma_queues(dqm))
 				return -EINVAL;
 
@@ -1901,6 +1928,7 @@ static int allocate_sdma_queue(struct device_queue_manager *dqm,
 			return -ENOMEM;
 		}
 	}
+	q->properties.is_oversubscribed = is_oversubscribed;
 
 	pr_debug("SDMA engine id: %d\n", q->properties.sdma_engine_id);
 	pr_debug("SDMA queue id: %d\n", q->properties.sdma_queue_id);
@@ -1914,7 +1942,11 @@ static void deallocate_sdma_queue(struct device_queue_manager *dqm,
 	if (q->properties.type == KFD_QUEUE_TYPE_SDMA) {
 		if (q->sdma_id >= get_num_sdma_queues(dqm))
 			return;
-		set_bit(q->sdma_id, dqm->sdma_bitmap);
+		/* Don't return oversubscribed queue IDs to bitmap.
+		 * They are shared by multiple queues and managed via round-robin.
+		 */
+		if (!q->properties.is_oversubscribed)
+			set_bit(q->sdma_id, dqm->sdma_bitmap);
 	} else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) {
 		if (q->sdma_id >= get_num_xgmi_sdma_queues(dqm))
 			return;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
index c9f9f7a87111..81626e657055 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
@@ -255,6 +255,10 @@ struct device_queue_manager {
 	unsigned int		gws_queue_count;
 	unsigned int		total_queue_count;
 	unsigned int		next_pipe_to_allocate;
+	/* Monotonically increasing counter used to round-robin oversubscribed
+	 * SDMA queues across the available HW queue slots.
+	 */
+	unsigned int		sdma_oversub_rotor;
 	unsigned int		*allocated_queues;
 	DECLARE_BITMAP(sdma_bitmap, KFD_MAX_SDMA_QUEUES);
 	DECLARE_BITMAP(xgmi_sdma_bitmap, KFD_MAX_SDMA_QUEUES);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index d8631847f0eb..5fff5e55fb09 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -531,6 +531,7 @@ struct queue_properties {
 	bool is_dbg_wa;
 	bool is_user_cu_masked;
 	bool is_reset;
+	bool is_oversubscribed;
 	/* Not relevant for user mode queues in cp scheduling */
 	unsigned int vmid;
 	/* Relevant only for sdma queues*/
-- 
2.43.0


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

* RE: [PATCH] drm/amdkfd: Enable SDMA queue oversubscription for GFX 12.0.x
  2026-08-20 15:36 [PATCH] drm/amdkfd: Enable SDMA queue oversubscription for GFX 12.0.x Sreekant Somasekharan
@ 2026-08-27 16:27 ` Somasekharan, Sreekant
  2026-08-27 16:39 ` Kuehling, Felix
  1 sibling, 0 replies; 3+ messages in thread
From: Somasekharan, Sreekant @ 2026-08-27 16:27 UTC (permalink / raw)
  To: amd-gfx@lists.freedesktop.org
  Cc: Kasiviswanathan, Harish, Kuehling, Felix, Yang, Philip

AMD General

ping

Regards,

-Sreekant


-----Original Message-----
From: Somasekharan, Sreekant <Sreekant.Somasekharan@amd.com>
Sent: August 20, 2026 11:36 AM
To: amd-gfx@lists.freedesktop.org
Cc: Kasiviswanathan, Harish <Harish.Kasiviswanathan@amd.com>; Somasekharan, Sreekant <Sreekant.Somasekharan@amd.com>
Subject: [PATCH] drm/amdkfd: Enable SDMA queue oversubscription for GFX 12.0.x

When all HW SDMA slots are exhausted on GFX 12.0.x with MES enabled, allow new queues to reuse HW queue IDs round-robin via a dedicated monotonic rotor. Each oversubscribed queue gets a unique doorbell from the per-process bitmap pool so MES can multiplex them independently.

Normal SDMA queues and all other GPU generations are unaffected.

Assisted-by: Claude:Sonnet 4.6
Signed-off-by: Sreekant Somasekharan <Sreekant.Somasekharan@amd.com>
---
 .../drm/amd/amdkfd/kfd_device_queue_manager.c | 54 +++++++++++++++----  .../drm/amd/amdkfd/kfd_device_queue_manager.h |  4 ++
 drivers/gpu/drm/amd/amdkfd/kfd_priv.h         |  1 +
 3 files changed, 48 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index a23384571193..10a672b87ca5 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -556,8 +556,9 @@ static int allocate_doorbell(struct qcm_process_device *qpd,
                        return -EINVAL;

                q->doorbell_id = q->properties.queue_id;
-       } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA ||
-                       q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) {
+       } else if ((q->properties.type == KFD_QUEUE_TYPE_SDMA ||
+                       q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) &&
+                       !q->properties.is_oversubscribed) {
                /* For SDMA queues on SOC15 with 8-byte doorbell, use static
                 * doorbell assignments based on the engine and queue id.
                 * The doobell index distance between RLC (2*i) and (2*i+1) @@ -583,7 +584,10 @@ static int allocate_doorbell(struct qcm_process_device *qpd,
                        return -EINVAL;
                q->doorbell_id = valid_id;
        } else {
-               /* For CP queues on SOC15 */
+               /* For CP queues on SOC15, and oversubscribed SDMA queues which
+                * reuse HW queue ids and so need a unique doorbell allocated
+                * from the per-process bitmap pool.
+                */
                if (restore_id) {
                        if (*restore_id >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
                                return -EINVAL;
@@ -621,9 +625,14 @@ static void deallocate_doorbell(struct qcm_process_device *qpd,
        unsigned int old;
        struct kfd_node *dev = qpd->dqm->dev;

+       /* Oversubscribed SDMA queues allocate a doorbell from the bitmap pool
+        * (like CP queues), so they must be freed; normal SDMA queues use
+        * static doorbell assignments and must not be.
+        */
        if (!KFD_IS_SOC15(dev) ||
-           q->properties.type == KFD_QUEUE_TYPE_SDMA ||
-           q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)
+           ((q->properties.type == KFD_QUEUE_TYPE_SDMA ||
+             q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) &&
+            !q->properties.is_oversubscribed))
                return;

        old = test_and_clear_bit(q->doorbell_id, qpd->doorbell_bitmap); @@ -1800,15 +1809,33 @@ static int allocate_sdma_queue(struct device_queue_manager *dqm,  {
        struct device *dev = dqm->dev->adev->dev;
        int bit;
+       bool is_oversubscribed = false;

        if (q->properties.type == KFD_QUEUE_TYPE_SDMA) {
                if (bitmap_empty(dqm->sdma_bitmap, get_num_sdma_queues(dqm))) {
-                       dev_warn(dev, "No more SDMA queue to allocate (%d total queues)\n",
-                                get_num_sdma_queues(dqm));
-                       return -ENOMEM;
-               }
+                       /* All HW queues are busy. On GFX 12.0.x under MES,
+                        * oversubscribe by reusing a HW queue id round-robin;
+                        * MES multiplexes the SW queues via their unique
+                        * doorbells. The non-MES HWS runlist path cannot express
+                        * duplicate sdma_ids, so it still fails with -ENOMEM.
+                        */
+                       unsigned int num_reserved, num_available;
+
+                       if (KFD_GC_VERSION(dqm->dev) < IP_VERSION(12, 0, 0) ||
+                           KFD_GC_VERSION(dqm->dev) >= IP_VERSION(12, 1, 0) ||
+                           !dqm->dev->kfd->shared_resources.enable_mes) {
+                               dev_warn(dev, "No more SDMA queue to allocate (%d total queues)\n",
+                                        get_num_sdma_queues(dqm));
+                               return -ENOMEM;
+                       }

-               if (restore_sdma_id) {
+                       num_reserved = kfd_get_num_sdma_engines(dqm->dev) *
+                               dqm->dev->kfd->device_info.num_reserved_sdma_queues_per_engine;
+                       num_available = get_num_sdma_queues(dqm) - num_reserved;
+                       q->sdma_id = num_reserved +
+                               dqm->sdma_oversub_rotor++ % num_available;
+                       is_oversubscribed = true;
+               } else if (restore_sdma_id) {
                        if (*restore_sdma_id >= get_num_sdma_queues(dqm))
                                return -EINVAL;

@@ -1901,6 +1928,7 @@ static int allocate_sdma_queue(struct device_queue_manager *dqm,
                        return -ENOMEM;
                }
        }
+       q->properties.is_oversubscribed = is_oversubscribed;

        pr_debug("SDMA engine id: %d\n", q->properties.sdma_engine_id);
        pr_debug("SDMA queue id: %d\n", q->properties.sdma_queue_id); @@ -1914,7 +1942,11 @@ static void deallocate_sdma_queue(struct device_queue_manager *dqm,
        if (q->properties.type == KFD_QUEUE_TYPE_SDMA) {
                if (q->sdma_id >= get_num_sdma_queues(dqm))
                        return;
-               set_bit(q->sdma_id, dqm->sdma_bitmap);
+               /* Don't return oversubscribed queue IDs to bitmap.
+                * They are shared by multiple queues and managed via round-robin.
+                */
+               if (!q->properties.is_oversubscribed)
+                       set_bit(q->sdma_id, dqm->sdma_bitmap);
        } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) {
                if (q->sdma_id >= get_num_xgmi_sdma_queues(dqm))
                        return;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
index c9f9f7a87111..81626e657055 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
@@ -255,6 +255,10 @@ struct device_queue_manager {
        unsigned int            gws_queue_count;
        unsigned int            total_queue_count;
        unsigned int            next_pipe_to_allocate;
+       /* Monotonically increasing counter used to round-robin oversubscribed
+        * SDMA queues across the available HW queue slots.
+        */
+       unsigned int            sdma_oversub_rotor;
        unsigned int            *allocated_queues;
        DECLARE_BITMAP(sdma_bitmap, KFD_MAX_SDMA_QUEUES);
        DECLARE_BITMAP(xgmi_sdma_bitmap, KFD_MAX_SDMA_QUEUES); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index d8631847f0eb..5fff5e55fb09 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -531,6 +531,7 @@ struct queue_properties {
        bool is_dbg_wa;
        bool is_user_cu_masked;
        bool is_reset;
+       bool is_oversubscribed;
        /* Not relevant for user mode queues in cp scheduling */
        unsigned int vmid;
        /* Relevant only for sdma queues*/
--
2.43.0


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

* Re: [PATCH] drm/amdkfd: Enable SDMA queue oversubscription for GFX 12.0.x
  2026-08-20 15:36 [PATCH] drm/amdkfd: Enable SDMA queue oversubscription for GFX 12.0.x Sreekant Somasekharan
  2026-08-27 16:27 ` Somasekharan, Sreekant
@ 2026-08-27 16:39 ` Kuehling, Felix
  1 sibling, 0 replies; 3+ messages in thread
From: Kuehling, Felix @ 2026-08-27 16:39 UTC (permalink / raw)
  To: Sreekant Somasekharan, amd-gfx; +Cc: harish.kasiviswanathan


On 2026-08-20 11:36, Sreekant Somasekharan wrote:
> When all HW SDMA slots are exhausted on GFX 12.0.x with MES enabled,
> allow new queues to reuse HW queue IDs round-robin via a dedicated
> monotonic rotor. Each oversubscribed queue gets a unique doorbell from
> the per-process bitmap pool so MES can multiplex them independently.

This special handling of doorbells for oversubscribed SDMA queues is 
only needed if you use more queues than doorbells _in the same process_. 
Across multiple processes this is not needed, because each process gets 
a unique set of doorbells.

Is the goal of this change really to enable oversubscription of SDMA 
queue slots by a single process? Is that even useful? Do you have a use 
case for that?

Regards,
   Felix


>
> Normal SDMA queues and all other GPU generations are unaffected.
>
> Assisted-by: Claude:Sonnet 4.6
> Signed-off-by: Sreekant Somasekharan <Sreekant.Somasekharan@amd.com>
> ---
>   .../drm/amd/amdkfd/kfd_device_queue_manager.c | 54 +++++++++++++++----
>   .../drm/amd/amdkfd/kfd_device_queue_manager.h |  4 ++
>   drivers/gpu/drm/amd/amdkfd/kfd_priv.h         |  1 +
>   3 files changed, 48 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
> index a23384571193..10a672b87ca5 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
> @@ -556,8 +556,9 @@ static int allocate_doorbell(struct qcm_process_device *qpd,
>   			return -EINVAL;
>   
>   		q->doorbell_id = q->properties.queue_id;
> -	} else if (q->properties.type == KFD_QUEUE_TYPE_SDMA ||
> -			q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) {
> +	} else if ((q->properties.type == KFD_QUEUE_TYPE_SDMA ||
> +			q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) &&
> +			!q->properties.is_oversubscribed) {
>   		/* For SDMA queues on SOC15 with 8-byte doorbell, use static
>   		 * doorbell assignments based on the engine and queue id.
>   		 * The doobell index distance between RLC (2*i) and (2*i+1)
> @@ -583,7 +584,10 @@ static int allocate_doorbell(struct qcm_process_device *qpd,
>   			return -EINVAL;
>   		q->doorbell_id = valid_id;
>   	} else {
> -		/* For CP queues on SOC15 */
> +		/* For CP queues on SOC15, and oversubscribed SDMA queues which
> +		 * reuse HW queue ids and so need a unique doorbell allocated
> +		 * from the per-process bitmap pool.
> +		 */
>   		if (restore_id) {
>   			if (*restore_id >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
>   				return -EINVAL;
> @@ -621,9 +625,14 @@ static void deallocate_doorbell(struct qcm_process_device *qpd,
>   	unsigned int old;
>   	struct kfd_node *dev = qpd->dqm->dev;
>   
> +	/* Oversubscribed SDMA queues allocate a doorbell from the bitmap pool
> +	 * (like CP queues), so they must be freed; normal SDMA queues use
> +	 * static doorbell assignments and must not be.
> +	 */
>   	if (!KFD_IS_SOC15(dev) ||
> -	    q->properties.type == KFD_QUEUE_TYPE_SDMA ||
> -	    q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)
> +	    ((q->properties.type == KFD_QUEUE_TYPE_SDMA ||
> +	      q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) &&
> +	     !q->properties.is_oversubscribed))
>   		return;
>   
>   	old = test_and_clear_bit(q->doorbell_id, qpd->doorbell_bitmap);
> @@ -1800,15 +1809,33 @@ static int allocate_sdma_queue(struct device_queue_manager *dqm,
>   {
>   	struct device *dev = dqm->dev->adev->dev;
>   	int bit;
> +	bool is_oversubscribed = false;
>   
>   	if (q->properties.type == KFD_QUEUE_TYPE_SDMA) {
>   		if (bitmap_empty(dqm->sdma_bitmap, get_num_sdma_queues(dqm))) {
> -			dev_warn(dev, "No more SDMA queue to allocate (%d total queues)\n",
> -				 get_num_sdma_queues(dqm));
> -			return -ENOMEM;
> -		}
> +			/* All HW queues are busy. On GFX 12.0.x under MES,
> +			 * oversubscribe by reusing a HW queue id round-robin;
> +			 * MES multiplexes the SW queues via their unique
> +			 * doorbells. The non-MES HWS runlist path cannot express
> +			 * duplicate sdma_ids, so it still fails with -ENOMEM.
> +			 */
> +			unsigned int num_reserved, num_available;
> +
> +			if (KFD_GC_VERSION(dqm->dev) < IP_VERSION(12, 0, 0) ||
> +			    KFD_GC_VERSION(dqm->dev) >= IP_VERSION(12, 1, 0) ||
> +			    !dqm->dev->kfd->shared_resources.enable_mes) {
> +				dev_warn(dev, "No more SDMA queue to allocate (%d total queues)\n",
> +					 get_num_sdma_queues(dqm));
> +				return -ENOMEM;
> +			}
>   
> -		if (restore_sdma_id) {
> +			num_reserved = kfd_get_num_sdma_engines(dqm->dev) *
> +				dqm->dev->kfd->device_info.num_reserved_sdma_queues_per_engine;
> +			num_available = get_num_sdma_queues(dqm) - num_reserved;
> +			q->sdma_id = num_reserved +
> +				dqm->sdma_oversub_rotor++ % num_available;
> +			is_oversubscribed = true;
> +		} else if (restore_sdma_id) {
>   			if (*restore_sdma_id >= get_num_sdma_queues(dqm))
>   				return -EINVAL;
>   
> @@ -1901,6 +1928,7 @@ static int allocate_sdma_queue(struct device_queue_manager *dqm,
>   			return -ENOMEM;
>   		}
>   	}
> +	q->properties.is_oversubscribed = is_oversubscribed;
>   
>   	pr_debug("SDMA engine id: %d\n", q->properties.sdma_engine_id);
>   	pr_debug("SDMA queue id: %d\n", q->properties.sdma_queue_id);
> @@ -1914,7 +1942,11 @@ static void deallocate_sdma_queue(struct device_queue_manager *dqm,
>   	if (q->properties.type == KFD_QUEUE_TYPE_SDMA) {
>   		if (q->sdma_id >= get_num_sdma_queues(dqm))
>   			return;
> -		set_bit(q->sdma_id, dqm->sdma_bitmap);
> +		/* Don't return oversubscribed queue IDs to bitmap.
> +		 * They are shared by multiple queues and managed via round-robin.
> +		 */
> +		if (!q->properties.is_oversubscribed)
> +			set_bit(q->sdma_id, dqm->sdma_bitmap);
>   	} else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) {
>   		if (q->sdma_id >= get_num_xgmi_sdma_queues(dqm))
>   			return;
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
> index c9f9f7a87111..81626e657055 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
> @@ -255,6 +255,10 @@ struct device_queue_manager {
>   	unsigned int		gws_queue_count;
>   	unsigned int		total_queue_count;
>   	unsigned int		next_pipe_to_allocate;
> +	/* Monotonically increasing counter used to round-robin oversubscribed
> +	 * SDMA queues across the available HW queue slots.
> +	 */
> +	unsigned int		sdma_oversub_rotor;
>   	unsigned int		*allocated_queues;
>   	DECLARE_BITMAP(sdma_bitmap, KFD_MAX_SDMA_QUEUES);
>   	DECLARE_BITMAP(xgmi_sdma_bitmap, KFD_MAX_SDMA_QUEUES);
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> index d8631847f0eb..5fff5e55fb09 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> @@ -531,6 +531,7 @@ struct queue_properties {
>   	bool is_dbg_wa;
>   	bool is_user_cu_masked;
>   	bool is_reset;
> +	bool is_oversubscribed;
>   	/* Not relevant for user mode queues in cp scheduling */
>   	unsigned int vmid;
>   	/* Relevant only for sdma queues*/

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

end of thread, other threads:[~2026-08-27 16:39 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 15:36 [PATCH] drm/amdkfd: Enable SDMA queue oversubscription for GFX 12.0.x Sreekant Somasekharan
2026-08-27 16:27 ` Somasekharan, Sreekant
2026-08-27 16:39 ` Kuehling, Felix

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