Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/18] drm/xe: Multi Queue feature support
@ 2025-11-21  3:51 Niranjana Vishwanathapura
  2025-11-21  3:51 ` [PATCH v3 01/18] drm/xe/multi_queue: Add multi_queue_enable_mask to gt information Niranjana Vishwanathapura
                   ` (23 more replies)
  0 siblings, 24 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

Multi Queue is a new mode of execution supported by the compute and
blitter copy command streamers (CCS and BCS, respectively). It is an
enhancement of the existing hardware architecture and leverages the
same submission model. It enables support for efficient, parallel
execution of multiple queues within a single context.

Add support for multi-queue feature and enable it on xe3p_xpc.

The associated IGT patch series is,
https://patchwork.freedesktop.org/series/156866/

The Compute UMD usecase is,
https://github.com/intel/compute-runtime/pull/862

Changes in v2:
- Rename multi_queue_enable_mask to multi_queue_engine_class_mask.
- Remove group->lock, fix function semantics, add additional comments,
  add asserts, update uapi kernel-doc, move group->list_lock to right
  patch, add XE_BO_FLAG_GGTT_INVALIDATE for cgp bo.
- Fix G2H_LEN_DW_MULTI_QUEUE_CONTEXT value.
- Add fs_reclaim lock dependency, add bspec ref, other minor cleanups.

Changes in v3:
- Add patch "drm/xe/xe3p: Disable GuC Dynamic ICS for Xe3p"
- Add patch "drm/xe/multi_queue: Reset GT upon CGP_SYNC failure"
- Code refactoring and kernel-doc update
- Assert CGP_SYNC message length is valid
- For CGP bo use PINNED_LATE_RESTORE/USER_VRAM/GGTT_INVALIDATE flags
- Properly handle cleanup of multi-queue group

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>

Gustavo Sousa (1):
  drm/xe/xe3p: Disable GuC Dynamic ICS for Xe3p

Niranjana Vishwanathapura (17):
  drm/xe/multi_queue: Add multi_queue_enable_mask to gt information
  drm/xe/multi_queue: Add user interface for multi queue support
  drm/xe/multi_queue: Add GuC interface for multi queue support
  drm/xe/multi_queue: Add multi queue priority property
  drm/xe/multi_queue: Handle invalid exec queue property setting
  drm/xe/multi_queue: Add exec_queue set_property ioctl support
  drm/xe/multi_queue: Add support for multi queue dynamic priority
    change
  drm/xe/multi_queue: Add multi queue information to guc_info dump
  drm/xe/multi_queue: Handle tearing down of a multi queue
  drm/xe/multi_queue: Set QUEUE_DRAIN_MODE for Multi Queue batches
  drm/xe/multi_queue: Handle CGP context error
  drm/xe/multi_queue: Reset GT upon CGP_SYNC failure
  drm/xe/multi_queue: Tracepoint support
  drm/xe/multi_queue: Support active group after primary is destroyed
  drm/xe/doc: Add documentation for Multi Queue Group
  drm/xe/doc: Add documentation for Multi Queue Group GuC interface
  drm/xe/multi_queue: Enable multi_queue on xe3p_xpc

 Documentation/gpu/xe/xe_exec_queue.rst        |  14 +
 drivers/gpu/drm/xe/abi/guc_actions_abi.h      |   4 +
 .../gpu/drm/xe/instructions/xe_gpu_commands.h |   1 +
 drivers/gpu/drm/xe/xe_debugfs.c               |   2 +
 drivers/gpu/drm/xe/xe_device.c                |   9 +-
 drivers/gpu/drm/xe/xe_exec_queue.c            | 428 +++++++++++-
 drivers/gpu/drm/xe/xe_exec_queue.h            |  51 ++
 drivers/gpu/drm/xe/xe_exec_queue_types.h      |  57 ++
 drivers/gpu/drm/xe/xe_gt_types.h              |   5 +
 drivers/gpu/drm/xe/xe_guc.c                   |   7 +
 drivers/gpu/drm/xe/xe_guc_ct.c                |   8 +
 drivers/gpu/drm/xe/xe_guc_fwif.h              |   3 +
 drivers/gpu/drm/xe/xe_guc_submit.c            | 627 ++++++++++++++++--
 drivers/gpu/drm/xe/xe_guc_submit.h            |   3 +
 drivers/gpu/drm/xe/xe_guc_submit_types.h      |  13 +
 drivers/gpu/drm/xe/xe_lrc.c                   |  29 +
 drivers/gpu/drm/xe/xe_lrc.h                   |   3 +
 drivers/gpu/drm/xe/xe_pci.c                   |   3 +
 drivers/gpu/drm/xe/xe_pci_types.h             |   1 +
 drivers/gpu/drm/xe/xe_ring_ops.c              |  68 +-
 drivers/gpu/drm/xe/xe_trace.h                 |  46 ++
 include/uapi/drm/xe_drm.h                     |  44 ++
 22 files changed, 1335 insertions(+), 91 deletions(-)

-- 
2.43.0


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

* [PATCH v3 01/18] drm/xe/multi_queue: Add multi_queue_enable_mask to gt information
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-21  3:51 ` [PATCH v3 02/18] drm/xe/multi_queue: Add user interface for multi queue support Niranjana Vishwanathapura
                   ` (22 subsequent siblings)
  23 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

Add multi_queue_enable_mask field to the gt information structure
which is bitmask of all engine classes with multi queue support
enabled.

v2: Rename multi_queue_enable_mask to multi_queue_engine_class_mask
    (Matt Brost)

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_debugfs.c   | 2 ++
 drivers/gpu/drm/xe/xe_gt_types.h  | 5 +++++
 drivers/gpu/drm/xe/xe_pci.c       | 1 +
 drivers/gpu/drm/xe/xe_pci_types.h | 1 +
 4 files changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
index 1d5a2a43a9d7..330855470a75 100644
--- a/drivers/gpu/drm/xe/xe_debugfs.c
+++ b/drivers/gpu/drm/xe/xe_debugfs.c
@@ -93,6 +93,8 @@ static int info(struct seq_file *m, void *data)
 			   xe_force_wake_ref(gt_to_fw(gt), XE_FW_GT));
 		drm_printf(&p, "gt%d engine_mask 0x%llx\n", id,
 			   gt->info.engine_mask);
+		drm_printf(&p, "gt%d multi_queue_engine_class_mask 0x%x\n", id,
+			   gt->info.multi_queue_engine_class_mask);
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h
index 0a728180b6fe..5318d92fd473 100644
--- a/drivers/gpu/drm/xe/xe_gt_types.h
+++ b/drivers/gpu/drm/xe/xe_gt_types.h
@@ -140,6 +140,11 @@ struct xe_gt {
 		u64 engine_mask;
 		/** @info.gmdid: raw GMD_ID value from hardware */
 		u32 gmdid;
+		/**
+		 * @multi_queue_engine_class_mask: Bitmask of engine classes with
+		 * multi queue support enabled.
+		 */
+		u16 multi_queue_engine_class_mask;
 		/** @info.id: Unique ID of this GT within the PCI Device */
 		u8 id;
 		/** @info.has_indirect_ring_state: GT has indirect ring state support */
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index 10eb18bc740e..f9464398e3ea 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -754,6 +754,7 @@ static struct xe_gt *alloc_primary_gt(struct xe_tile *tile,
 	gt->info.type = XE_GT_TYPE_MAIN;
 	gt->info.id = tile->id * xe->info.max_gt_per_tile;
 	gt->info.has_indirect_ring_state = graphics_desc->has_indirect_ring_state;
+	gt->info.multi_queue_engine_class_mask = graphics_desc->multi_queue_engine_class_mask;
 	gt->info.engine_mask = graphics_desc->hw_engine_mask;
 
 	/*
diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h
index 9892c063a9c5..975e9857f70c 100644
--- a/drivers/gpu/drm/xe/xe_pci_types.h
+++ b/drivers/gpu/drm/xe/xe_pci_types.h
@@ -58,6 +58,7 @@ struct xe_device_desc {
 
 struct xe_graphics_desc {
 	u64 hw_engine_mask;	/* hardware engines provided by graphics IP */
+	u16 multi_queue_engine_class_mask; /* bitmask of engine classes which support multi queue */
 
 	u8 has_asid:1;
 	u8 has_atomic_enable_pte_bit:1;
-- 
2.43.0


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

* [PATCH v3 02/18] drm/xe/multi_queue: Add user interface for multi queue support
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
  2025-11-21  3:51 ` [PATCH v3 01/18] drm/xe/multi_queue: Add multi_queue_enable_mask to gt information Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-21 22:51   ` Matthew Brost
  2025-11-21  3:51 ` [PATCH v3 03/18] drm/xe/multi_queue: Add GuC " Niranjana Vishwanathapura
                   ` (21 subsequent siblings)
  23 siblings, 1 reply; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

Multi Queue is a new mode of execution supported by the compute and
blitter copy command streamers (CCS and BCS, respectively). It is an
enhancement of the existing hardware architecture and leverages the
same submission model. It enables support for efficient, parallel
execution of multiple queues within a single context. All the queues
of a group must use the same address space (VM).

The new DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE execution queue
property supports creating a multi queue group and adding queues to
a queue group. All queues of a multi queue group share the same
context.

A exec queue create ioctl call with above property specified with value
DRM_XE_SUPER_GROUP_CREATE will create a new multi queue group with the
queue being created as the primary queue (aka q0) of the group. To add
secondary queues to the group, they need to be created with the above
property with id of the primary queue as the value. The properties of
the primary queue (like priority, timeslice) applies to the whole group.
So, these properties can't be set for secondary queues of a group.

Once destroyed, the secondary queues of a multi queue group can't be
replaced. However, they can be dynamically added to the group up to a
total of 64 queues per group. Once the primary queue is destroyed,
secondary queues can't be added to the queue group.

v2: Remove group->lock, fix xe_exec_queue_group_add()/delete()
    function semantics, add additional comments, remove unused
    group->list_lock, add XE_BO_FLAG_GGTT_INVALIDATE for cgp bo,
    Assert LRC is valid, update uapi kernel doc.
    (Matt Brost)
v3: Use XE_BO_FLAG_PINNED_LATE_RESTORE/USER_VRAM/GGTT_INVALIDATE
    flags for cgp bo (Matt)

Signed-off-by: Stuart Summers <stuart.summers@intel.com>
Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
---
 drivers/gpu/drm/xe/xe_exec_queue.c       | 194 ++++++++++++++++++++++-
 drivers/gpu/drm/xe/xe_exec_queue.h       |  47 ++++++
 drivers/gpu/drm/xe/xe_exec_queue_types.h |  26 +++
 include/uapi/drm/xe_drm.h                |  10 ++
 4 files changed, 275 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index 8724f8de67e2..330b5103222c 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -13,6 +13,7 @@
 #include <drm/drm_syncobj.h>
 #include <uapi/drm/xe_drm.h>
 
+#include "xe_bo.h"
 #include "xe_dep_scheduler.h"
 #include "xe_device.h"
 #include "xe_gt.h"
@@ -63,6 +64,33 @@ enum xe_exec_queue_sched_prop {
 static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue *q,
 				      u64 extensions, int ext_number);
 
+static void xe_exec_queue_group_cleanup(struct xe_exec_queue *q)
+{
+	struct xe_exec_queue_group *group = q->multi_queue.group;
+	struct xe_lrc *lrc;
+	unsigned long idx;
+
+	if (xe_exec_queue_is_multi_queue_secondary(q)) {
+		/*
+		 * Put pairs with get from xe_exec_queue_lookup() call
+		 * in xe_exec_queue_group_validate().
+		 */
+		xe_exec_queue_put(xe_exec_queue_multi_queue_primary(q));
+		return;
+	}
+
+	if (!group)
+		return;
+
+	/* Primary queue cleanup */
+	xa_for_each(&group->xa, idx, lrc)
+		xe_lrc_put(lrc);
+
+	xa_destroy(&group->xa);
+	xe_bo_unpin_map_no_vm(group->cgp_bo);
+	kfree(group);
+}
+
 static void __xe_exec_queue_free(struct xe_exec_queue *q)
 {
 	int i;
@@ -73,6 +101,10 @@ static void __xe_exec_queue_free(struct xe_exec_queue *q)
 
 	if (xe_exec_queue_uses_pxp(q))
 		xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q);
+
+	if (xe_exec_queue_is_multi_queue(q))
+		xe_exec_queue_group_cleanup(q);
+
 	if (q->vm)
 		xe_vm_put(q->vm);
 
@@ -567,6 +599,147 @@ exec_queue_set_pxp_type(struct xe_device *xe, struct xe_exec_queue *q, u64 value
 	return xe_pxp_exec_queue_set_type(xe->pxp, q, DRM_XE_PXP_TYPE_HWDRM);
 }
 
+static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue *q)
+{
+	struct xe_tile *tile = gt_to_tile(q->gt);
+	struct xe_exec_queue_group *group;
+	struct xe_bo *bo;
+
+	group = kzalloc(sizeof(*group), GFP_KERNEL);
+	if (!group)
+		return -ENOMEM;
+
+	bo = xe_bo_create_pin_map_novm(xe, tile, SZ_4K, ttm_bo_type_kernel,
+				       XE_BO_FLAG_VRAM_IF_DGFX(tile) |
+				       XE_BO_FLAG_PINNED_LATE_RESTORE |
+				       XE_BO_FLAG_FORCE_USER_VRAM |
+				       XE_BO_FLAG_GGTT_INVALIDATE |
+				       XE_BO_FLAG_GGTT, false);
+	if (IS_ERR(bo)) {
+		drm_err(&xe->drm, "CGP bo allocation for queue group failed: %ld\n",
+			PTR_ERR(bo));
+		kfree(group);
+		return PTR_ERR(bo);
+	}
+
+	xe_map_memset(xe, &bo->vmap, 0, 0, SZ_4K);
+
+	group->primary = q;
+	group->cgp_bo = bo;
+	xa_init_flags(&group->xa, XA_FLAGS_ALLOC1);
+	q->multi_queue.group = group;
+
+	return 0;
+}
+
+static inline bool xe_exec_queue_supports_multi_queue(struct xe_exec_queue *q)
+{
+	return q->gt->info.multi_queue_engine_class_mask & BIT(q->class);
+}
+
+static int xe_exec_queue_group_validate(struct xe_device *xe, struct xe_exec_queue *q,
+					u32 primary_id)
+{
+	struct xe_exec_queue_group *group;
+	struct xe_exec_queue *primary;
+	int ret;
+
+	/*
+	 * Get from below xe_exec_queue_lookup() pairs with put
+	 * in xe_exec_queue_group_cleanup().
+	 */
+	primary = xe_exec_queue_lookup(q->vm->xef, primary_id);
+	if (XE_IOCTL_DBG(xe, !primary))
+		return -ENOENT;
+
+	if (XE_IOCTL_DBG(xe, !xe_exec_queue_is_multi_queue_primary(primary)) ||
+	    XE_IOCTL_DBG(xe, q->vm != primary->vm) ||
+	    XE_IOCTL_DBG(xe, q->logical_mask != primary->logical_mask)) {
+		ret = -EINVAL;
+		goto put_primary;
+	}
+
+	group = primary->multi_queue.group;
+	q->multi_queue.valid = true;
+	q->multi_queue.group = group;
+
+	return 0;
+put_primary:
+	xe_exec_queue_put(primary);
+	return ret;
+}
+
+#define XE_MAX_GROUP_SIZE	64
+static int xe_exec_queue_group_add(struct xe_device *xe, struct xe_exec_queue *q)
+{
+	struct xe_exec_queue_group *group = q->multi_queue.group;
+	u32 pos;
+	int err;
+
+	xe_assert(xe, xe_exec_queue_is_multi_queue_secondary(q));
+
+	/* Primary queue holds a reference to LRCs of all secondary queues */
+	err = xa_alloc(&group->xa, &pos, xe_lrc_get(q->lrc[0]),
+		       XA_LIMIT(1, XE_MAX_GROUP_SIZE - 1), GFP_KERNEL);
+	if (XE_IOCTL_DBG(xe, err)) {
+		xe_lrc_put(q->lrc[0]);
+
+		/* It is invalid if queue group limit is exceeded */
+		if (err == -EBUSY)
+			err = -EINVAL;
+
+		return err;
+	}
+
+	q->multi_queue.pos = pos;
+
+	return 0;
+}
+
+static void xe_exec_queue_group_delete(struct xe_device *xe, struct xe_exec_queue *q)
+{
+	struct xe_exec_queue_group *group = q->multi_queue.group;
+	struct xe_lrc *lrc;
+
+	xe_assert(xe, xe_exec_queue_is_multi_queue_secondary(q));
+
+	lrc = xa_erase(&group->xa, q->multi_queue.pos);
+	xe_assert(xe, lrc);
+	xe_lrc_put(lrc);
+}
+
+static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue *q,
+				      u64 value)
+{
+	if (XE_IOCTL_DBG(xe, !xe_exec_queue_supports_multi_queue(q)))
+		return -ENODEV;
+
+	if (XE_IOCTL_DBG(xe, !xe_device_uc_enabled(xe)))
+		return -EOPNOTSUPP;
+
+	if (XE_IOCTL_DBG(xe, xe_exec_queue_is_parallel(q)))
+		return -EINVAL;
+
+	if (XE_IOCTL_DBG(xe, xe_exec_queue_is_multi_queue(q)))
+		return -EINVAL;
+
+	if (value & DRM_XE_MULTI_GROUP_CREATE) {
+		if (XE_IOCTL_DBG(xe, value & ~DRM_XE_MULTI_GROUP_CREATE))
+			return -EINVAL;
+
+		q->multi_queue.valid = true;
+		q->multi_queue.is_primary = true;
+		q->multi_queue.pos = 0;
+		return 0;
+	}
+
+	/* While adding secondary queues, the upper 32 bits must be 0 */
+	if (XE_IOCTL_DBG(xe, value & (~0ull << 32)))
+		return -EINVAL;
+
+	return xe_exec_queue_group_validate(xe, q, value);
+}
+
 typedef int (*xe_exec_queue_set_property_fn)(struct xe_device *xe,
 					     struct xe_exec_queue *q,
 					     u64 value);
@@ -575,6 +748,7 @@ static const xe_exec_queue_set_property_fn exec_queue_set_property_funcs[] = {
 	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY] = exec_queue_set_priority,
 	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE] = exec_queue_set_timeslice,
 	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE] = exec_queue_set_pxp_type,
+	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP] = exec_queue_set_multi_group,
 };
 
 static int exec_queue_user_ext_set_property(struct xe_device *xe,
@@ -595,7 +769,8 @@ static int exec_queue_user_ext_set_property(struct xe_device *xe,
 	    XE_IOCTL_DBG(xe, ext.pad) ||
 	    XE_IOCTL_DBG(xe, ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY &&
 			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE &&
-			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE))
+			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE &&
+			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP))
 		return -EINVAL;
 
 	idx = array_index_nospec(ext.property, ARRAY_SIZE(exec_queue_set_property_funcs));
@@ -644,6 +819,12 @@ static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue
 		return exec_queue_user_extensions(xe, q, ext.next_extension,
 						  ++ext_number);
 
+	if (xe_exec_queue_is_multi_queue_primary(q)) {
+		err = xe_exec_queue_group_init(xe, q);
+		if (XE_IOCTL_DBG(xe, err))
+			return err;
+	}
+
 	return 0;
 }
 
@@ -798,12 +979,18 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
 		if (IS_ERR(q))
 			return PTR_ERR(q);
 
+		if (xe_exec_queue_is_multi_queue_secondary(q)) {
+			err = xe_exec_queue_group_add(xe, q);
+			if (XE_IOCTL_DBG(xe, err))
+				goto put_exec_queue;
+		}
+
 		if (xe_vm_in_preempt_fence_mode(vm)) {
 			q->lr.context = dma_fence_context_alloc(1);
 
 			err = xe_vm_add_compute_exec_queue(vm, q);
 			if (XE_IOCTL_DBG(xe, err))
-				goto put_exec_queue;
+				goto delete_queue_group;
 		}
 
 		if (q->vm && q->hwe->hw_engine_group) {
@@ -826,6 +1013,9 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
 
 kill_exec_queue:
 	xe_exec_queue_kill(q);
+delete_queue_group:
+	if (xe_exec_queue_is_multi_queue_secondary(q))
+		xe_exec_queue_group_delete(xe, q);
 put_exec_queue:
 	xe_exec_queue_put(q);
 	return err;
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.h b/drivers/gpu/drm/xe/xe_exec_queue.h
index fda4d4f9bda8..e6daa40003f2 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue.h
@@ -66,6 +66,53 @@ static inline bool xe_exec_queue_uses_pxp(struct xe_exec_queue *q)
 	return q->pxp.type;
 }
 
+/**
+ * xe_exec_queue_is_multi_queue() - Whether an exec_queue is part of a queue group.
+ * @q: The exec_queue
+ *
+ * Return: True if the exec_queue is part of a queue group, false otherwise.
+ */
+static inline bool xe_exec_queue_is_multi_queue(struct xe_exec_queue *q)
+{
+	return q->multi_queue.valid;
+}
+
+/**
+ * xe_exec_queue_is_multi_queue_primary() - Whether an exec_queue is primary queue
+ * of a multi queue group.
+ * @q: The exec_queue
+ *
+ * Return: True if @q is primary queue of a queue group, false otherwise.
+ */
+static inline bool xe_exec_queue_is_multi_queue_primary(struct xe_exec_queue *q)
+{
+	return q->multi_queue.is_primary;
+}
+
+/**
+ * xe_exec_queue_is_multi_queue_secondary() - Whether an exec_queue is secondary queue
+ * of a multi queue group.
+ * @q: The exec_queue
+ *
+ * Return: True if @q is secondary queue of a queue group, false otherwise.
+ */
+static inline bool xe_exec_queue_is_multi_queue_secondary(struct xe_exec_queue *q)
+{
+	return xe_exec_queue_is_multi_queue(q) && !xe_exec_queue_is_multi_queue_primary(q);
+}
+
+/**
+ * xe_exec_queue_multi_queue_primary() - Get multi queue group's primary queue
+ * @q: The exec_queue
+ *
+ * If @q belongs to a multi queue group, then the primary queue of the group will
+ * be returned. Otherwise, @q will be returned.
+ */
+static inline struct xe_exec_queue *xe_exec_queue_multi_queue_primary(struct xe_exec_queue *q)
+{
+	return xe_exec_queue_is_multi_queue(q) ? q->multi_queue.group->primary : q;
+}
+
 bool xe_exec_queue_is_lr(struct xe_exec_queue *q);
 
 bool xe_exec_queue_is_idle(struct xe_exec_queue *q);
diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
index 771ffe35cd0c..f429b1952be9 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
@@ -32,6 +32,20 @@ enum xe_exec_queue_priority {
 	XE_EXEC_QUEUE_PRIORITY_COUNT
 };
 
+/**
+ * struct xe_exec_queue_group - Execution multi queue group
+ *
+ * Contains multi queue group information.
+ */
+struct xe_exec_queue_group {
+	/** @primary: Primary queue of this group */
+	struct xe_exec_queue *primary;
+	/** @cgp_bo: BO for the Context Group Page */
+	struct xe_bo *cgp_bo;
+	/** @xa: xarray to store LRCs */
+	struct xarray xa;
+};
+
 /**
  * struct xe_exec_queue - Execution queue
  *
@@ -111,6 +125,18 @@ struct xe_exec_queue {
 		struct xe_guc_exec_queue *guc;
 	};
 
+	/** @multi_queue: Multi queue information */
+	struct {
+		/** @multi_queue.group: Queue group information */
+		struct xe_exec_queue_group *group;
+		/** @multi_queue.pos: Position of queue within the multi-queue group */
+		u8 pos;
+		/** @multi_queue.valid: Queue belongs to a multi queue group */
+		u8 valid:1;
+		/** @multi_queue.is_primary: Is primary queue (Q0) of the group */
+		u8 is_primary:1;
+	} multi_queue;
+
 	/** @sched_props: scheduling properties */
 	struct {
 		/** @sched_props.timeslice_us: timeslice period in micro-seconds */
diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
index 47853659a705..4de21e0a4fcf 100644
--- a/include/uapi/drm/xe_drm.h
+++ b/include/uapi/drm/xe_drm.h
@@ -1252,6 +1252,14 @@ struct drm_xe_vm_bind {
  *    Given that going into a power-saving state kills PXP HWDRM sessions,
  *    runtime PM will be blocked while queues of this type are alive.
  *    All PXP queues will be killed if a PXP invalidation event occurs.
+ *  - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP - Create a multi-queue group
+ *    or add secondary queues to a multi-queue group.
+ *    If the extension's 'value' field has %DRM_XE_MULTI_GROUP_CREATE flag set,
+ *    then a new multi-queue group is created with this queue as the primary queue
+ *    (Q0). Otherwise, the queue gets added to the multi-queue group whose primary
+ *    queue's exec_queue_id is specified in the lower 32 bits of the 'value' field.
+ *    All the other non-relevant bits of extension's 'value' field while adding the
+ *    primary or the secondary queues of the group must be set to 0.
  *
  * The example below shows how to use @drm_xe_exec_queue_create to create
  * a simple exec_queue (no parallel submission) of class
@@ -1292,6 +1300,8 @@ struct drm_xe_exec_queue_create {
 #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY		0
 #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE		1
 #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE		2
+#define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP		3
+#define     DRM_XE_MULTI_GROUP_CREATE				(1ull << 63)
 	/** @extensions: Pointer to the first extension struct, if any */
 	__u64 extensions;
 
-- 
2.43.0


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

* [PATCH v3 03/18] drm/xe/multi_queue: Add GuC interface for multi queue support
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
  2025-11-21  3:51 ` [PATCH v3 01/18] drm/xe/multi_queue: Add multi_queue_enable_mask to gt information Niranjana Vishwanathapura
  2025-11-21  3:51 ` [PATCH v3 02/18] drm/xe/multi_queue: Add user interface for multi queue support Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-22 22:16   ` Matthew Brost
  2025-11-21  3:51 ` [PATCH v3 04/18] drm/xe/multi_queue: Add multi queue priority property Niranjana Vishwanathapura
                   ` (20 subsequent siblings)
  23 siblings, 1 reply; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

Implement GuC commands and response along with the Context
Group Page (CGP) interface for multi queue support.

Ensure that only primary queue (q0) of a multi queue group
communicate with GuC. The secondary queues of the group only
need to maintain LRCA and interface with drm scheduler.

Use primary queue's submit_wq for all secondary queues of a multi
queue group. This serialization avoids any locking around CGP
synchronization with GuC.

v2: Fix G2H_LEN_DW_MULTI_QUEUE_CONTEXT value, add more comments
    (Matt Brost)
v3: Minor code refactro, use xe_gt_assert

Signed-off-by: Stuart Summers <stuart.summers@intel.com>
Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
---
 drivers/gpu/drm/xe/abi/guc_actions_abi.h |   3 +
 drivers/gpu/drm/xe/xe_exec_queue_types.h |   2 +
 drivers/gpu/drm/xe/xe_guc_ct.c           |   4 +
 drivers/gpu/drm/xe/xe_guc_fwif.h         |   3 +
 drivers/gpu/drm/xe/xe_guc_submit.c       | 276 +++++++++++++++++++++--
 drivers/gpu/drm/xe/xe_guc_submit.h       |   1 +
 6 files changed, 267 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/xe/abi/guc_actions_abi.h b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
index 47756e4674a1..3e9fbed9cda6 100644
--- a/drivers/gpu/drm/xe/abi/guc_actions_abi.h
+++ b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
@@ -139,6 +139,9 @@ enum xe_guc_action {
 	XE_GUC_ACTION_DEREGISTER_G2G = 0x4508,
 	XE_GUC_ACTION_DEREGISTER_CONTEXT_DONE = 0x4600,
 	XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC = 0x4601,
+	XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE = 0x4602,
+	XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC = 0x4603,
+	XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE = 0x4604,
 	XE_GUC_ACTION_CLIENT_SOFT_RESET = 0x5507,
 	XE_GUC_ACTION_SET_ENG_UTIL_BUFF = 0x550A,
 	XE_GUC_ACTION_SET_DEVICE_ENGINE_ACTIVITY_BUFFER = 0x550C,
diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
index f429b1952be9..b9da51ab7eaf 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
@@ -44,6 +44,8 @@ struct xe_exec_queue_group {
 	struct xe_bo *cgp_bo;
 	/** @xa: xarray to store LRCs */
 	struct xarray xa;
+	/** @sync_pending: CGP_SYNC_DONE g2h response pending */
+	bool sync_pending;
 };
 
 /**
diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c
index 2697d711adb2..43a79bcdfb18 100644
--- a/drivers/gpu/drm/xe/xe_guc_ct.c
+++ b/drivers/gpu/drm/xe/xe_guc_ct.c
@@ -1307,6 +1307,7 @@ static int parse_g2h_event(struct xe_guc_ct *ct, u32 *msg, u32 len)
 	lockdep_assert_held(&ct->lock);
 
 	switch (action) {
+	case XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE:
 	case XE_GUC_ACTION_SCHED_CONTEXT_MODE_DONE:
 	case XE_GUC_ACTION_DEREGISTER_CONTEXT_DONE:
 	case XE_GUC_ACTION_SCHED_ENGINE_MODE_DONE:
@@ -1569,6 +1570,9 @@ static int process_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len)
 		ret = xe_guc_g2g_test_notification(guc, payload, adj_len);
 		break;
 #endif
+	case XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE:
+		ret = xe_guc_exec_queue_cgp_sync_done_handler(guc, payload, adj_len);
+		break;
 	default:
 		xe_gt_err(gt, "unexpected G2H action 0x%04x\n", action);
 	}
diff --git a/drivers/gpu/drm/xe/xe_guc_fwif.h b/drivers/gpu/drm/xe/xe_guc_fwif.h
index c90dd266e9cf..9b090d9b95f1 100644
--- a/drivers/gpu/drm/xe/xe_guc_fwif.h
+++ b/drivers/gpu/drm/xe/xe_guc_fwif.h
@@ -16,6 +16,7 @@
 #define G2H_LEN_DW_DEREGISTER_CONTEXT		3
 #define G2H_LEN_DW_TLB_INVALIDATE		3
 #define G2H_LEN_DW_G2G_NOTIFY_MIN		3
+#define G2H_LEN_DW_MULTI_QUEUE_CONTEXT		3
 
 #define GUC_ID_MAX			65535
 #define GUC_ID_UNKNOWN			0xffffffff
@@ -62,6 +63,8 @@ struct guc_ctxt_registration_info {
 	u32 wq_base_lo;
 	u32 wq_base_hi;
 	u32 wq_size;
+	u32 cgp_lo;
+	u32 cgp_hi;
 	u32 hwlrca_lo;
 	u32 hwlrca_hi;
 };
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 7e0882074a99..c68739fd7592 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -19,6 +19,7 @@
 #include "abi/guc_klvs_abi.h"
 #include "regs/xe_lrc_layout.h"
 #include "xe_assert.h"
+#include "xe_bo.h"
 #include "xe_devcoredump.h"
 #include "xe_device.h"
 #include "xe_exec_queue.h"
@@ -541,7 +542,8 @@ static void init_policies(struct xe_guc *guc, struct xe_exec_queue *q)
 	u32 slpc_exec_queue_freq_req = 0;
 	u32 preempt_timeout_us = q->sched_props.preempt_timeout_us;
 
-	xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q));
+	xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q) &&
+		     !xe_exec_queue_is_multi_queue_secondary(q));
 
 	if (q->flags & EXEC_QUEUE_FLAG_LOW_LATENCY)
 		slpc_exec_queue_freq_req |= SLPC_CTX_FREQ_REQ_IS_COMPUTE;
@@ -561,6 +563,8 @@ static void set_min_preemption_timeout(struct xe_guc *guc, struct xe_exec_queue
 {
 	struct exec_queue_policy policy;
 
+	xe_assert(guc_to_xe(guc), !xe_exec_queue_is_multi_queue_secondary(q));
+
 	__guc_exec_queue_policy_start_klv(&policy, q->guc->id);
 	__guc_exec_queue_policy_add_preemption_timeout(&policy, 1);
 
@@ -568,6 +572,11 @@ static void set_min_preemption_timeout(struct xe_guc *guc, struct xe_exec_queue
 		       __guc_exec_queue_policy_action_size(&policy), 0, 0);
 }
 
+static bool vf_recovery(struct xe_guc *guc)
+{
+	return xe_gt_recovery_pending(guc_to_gt(guc));
+}
+
 #define parallel_read(xe_, map_, field_) \
 	xe_map_rd_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
 			field_)
@@ -575,6 +584,117 @@ static void set_min_preemption_timeout(struct xe_guc *guc, struct xe_exec_queue
 	xe_map_wr_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
 			field_, val_)
 
+#define CGP_VERSION_MAJOR_SHIFT	8
+
+static void xe_guc_exec_queue_group_cgp_update(struct xe_device *xe,
+					       struct xe_exec_queue *q)
+{
+	struct xe_exec_queue_group *group = q->multi_queue.group;
+	u32 guc_id = group->primary->guc->id;
+
+	/* Currently implementing CGP version 1.0 */
+	xe_map_wr(xe, &group->cgp_bo->vmap, 0, u32,
+		  1 << CGP_VERSION_MAJOR_SHIFT);
+
+	xe_map_wr(xe, &group->cgp_bo->vmap,
+		  (32 + q->multi_queue.pos * 2) * sizeof(u32),
+		  u32, lower_32_bits(xe_lrc_descriptor(q->lrc[0])));
+
+	xe_map_wr(xe, &group->cgp_bo->vmap,
+		  (33 + q->multi_queue.pos * 2) * sizeof(u32),
+		  u32, guc_id);
+
+	if (q->multi_queue.pos / 32) {
+		xe_map_wr(xe, &group->cgp_bo->vmap, 17 * sizeof(u32),
+			  u32, BIT(q->multi_queue.pos % 32));
+		xe_map_wr(xe, &group->cgp_bo->vmap, 16 * sizeof(u32), u32, 0);
+	} else {
+		xe_map_wr(xe, &group->cgp_bo->vmap, 16 * sizeof(u32),
+			  u32, BIT(q->multi_queue.pos));
+		xe_map_wr(xe, &group->cgp_bo->vmap, 17 * sizeof(u32), u32, 0);
+	}
+}
+
+static void xe_guc_exec_queue_group_cgp_sync(struct xe_guc *guc,
+					     struct xe_exec_queue *q,
+					     const u32 *action, u32 len)
+{
+	struct xe_exec_queue_group *group = q->multi_queue.group;
+	struct xe_device *xe = guc_to_xe(guc);
+	long ret;
+
+	/*
+	 * As all queues of a multi queue group use single drm scheduler
+	 * submit workqueue, CGP synchronization with GuC are serialized.
+	 * Hence, no locking is required here.
+	 * Wait for any pending CGP_SYNC_DONE response before updating the
+	 * CGP page and sending CGP_SYNC message.
+	 */
+	ret = wait_event_timeout(guc->ct.wq,
+				 !READ_ONCE(group->sync_pending) ||
+				 xe_guc_read_stopped(guc), HZ);
+	if ((!ret && !vf_recovery(guc)) || xe_guc_read_stopped(guc)) {
+		xe_gt_warn(guc_to_gt(guc), "Wait for CGP_SYNC_DONE response failed!\n");
+		return;
+	}
+
+	xe_guc_exec_queue_group_cgp_update(xe, q);
+
+	WRITE_ONCE(group->sync_pending, true);
+	xe_guc_ct_send(&guc->ct, action, len, G2H_LEN_DW_MULTI_QUEUE_CONTEXT, 1);
+}
+
+static void __register_exec_queue_group(struct xe_guc *guc,
+					struct xe_exec_queue *q,
+					struct guc_ctxt_registration_info *info)
+{
+#define MAX_MULTI_QUEUE_REG_SIZE	(8)
+	u32 action[MAX_MULTI_QUEUE_REG_SIZE];
+	int len = 0;
+
+	action[len++] = XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE;
+	action[len++] = info->flags;
+	action[len++] = info->context_idx;
+	action[len++] = info->engine_class;
+	action[len++] = info->engine_submit_mask;
+	action[len++] = 0; /* Reserved */
+	action[len++] = info->cgp_lo;
+	action[len++] = info->cgp_hi;
+
+	xe_gt_assert(guc_to_gt(guc), len <= MAX_MULTI_QUEUE_REG_SIZE);
+#undef MAX_MULTI_QUEUE_REG_SIZE
+
+	/*
+	 * The above XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE do expect a
+	 * XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE response
+	 * from guc.
+	 */
+	xe_guc_exec_queue_group_cgp_sync(guc, q, action, len);
+}
+
+static void xe_guc_exec_queue_group_add(struct xe_guc *guc,
+					struct xe_exec_queue *q)
+{
+#define MAX_MULTI_QUEUE_CGP_SYNC_SIZE  (2)
+	u32 action[MAX_MULTI_QUEUE_CGP_SYNC_SIZE];
+	int len = 0;
+
+	xe_gt_assert(guc_to_gt(guc), xe_exec_queue_is_multi_queue_secondary(q));
+
+	action[len++] = XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC;
+	action[len++] = q->multi_queue.group->primary->guc->id;
+
+	xe_gt_assert(guc_to_gt(guc), len <= MAX_MULTI_QUEUE_CGP_SYNC_SIZE);
+#undef MAX_MULTI_QUEUE_CGP_SYNC_SIZE
+
+	/*
+	 * The above XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC do expect a
+	 * XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE response
+	 * from guc.
+	 */
+	xe_guc_exec_queue_group_cgp_sync(guc, q, action, len);
+}
+
 static void __register_mlrc_exec_queue(struct xe_guc *guc,
 				       struct xe_exec_queue *q,
 				       struct guc_ctxt_registration_info *info)
@@ -670,6 +790,13 @@ static void register_exec_queue(struct xe_exec_queue *q, int ctx_type)
 	info.flags = CONTEXT_REGISTRATION_FLAG_KMD |
 		FIELD_PREP(CONTEXT_REGISTRATION_FLAG_TYPE, ctx_type);
 
+	if (xe_exec_queue_is_multi_queue(q)) {
+		struct xe_exec_queue_group *group = q->multi_queue.group;
+
+		info.cgp_lo = xe_bo_ggtt_addr(group->cgp_bo);
+		info.cgp_hi = 0;
+	}
+
 	if (xe_exec_queue_is_parallel(q)) {
 		u64 ggtt_addr = xe_lrc_parallel_ggtt_addr(lrc);
 		struct iosys_map map = xe_lrc_parallel_map(lrc);
@@ -700,11 +827,18 @@ static void register_exec_queue(struct xe_exec_queue *q, int ctx_type)
 
 	set_exec_queue_registered(q);
 	trace_xe_exec_queue_register(q);
-	if (xe_exec_queue_is_parallel(q))
+	if (xe_exec_queue_is_multi_queue_primary(q))
+		__register_exec_queue_group(guc, q, &info);
+	else if (xe_exec_queue_is_parallel(q))
 		__register_mlrc_exec_queue(guc, q, &info);
-	else
+	else if (!xe_exec_queue_is_multi_queue_secondary(q))
 		__register_exec_queue(guc, &info);
-	init_policies(guc, q);
+
+	if (!xe_exec_queue_is_multi_queue_secondary(q))
+		init_policies(guc, q);
+
+	if (xe_exec_queue_is_multi_queue_secondary(q))
+		xe_guc_exec_queue_group_add(guc, q);
 }
 
 static u32 wq_space_until_wrap(struct xe_exec_queue *q)
@@ -712,11 +846,6 @@ static u32 wq_space_until_wrap(struct xe_exec_queue *q)
 	return (WQ_SIZE - q->guc->wqi_tail);
 }
 
-static bool vf_recovery(struct xe_guc *guc)
-{
-	return xe_gt_recovery_pending(guc_to_gt(guc));
-}
-
 static int wq_wait_for_space(struct xe_exec_queue *q, u32 wqi_size)
 {
 	struct xe_guc *guc = exec_queue_to_guc(q);
@@ -833,6 +962,12 @@ static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job)
 	if (exec_queue_suspended(q) && !xe_exec_queue_is_parallel(q))
 		return;
 
+	/*
+	 * All queues in a multi-queue group will use the primary queue
+	 * of the group to interface with GuC.
+	 */
+	q = xe_exec_queue_multi_queue_primary(q);
+
 	if (!exec_queue_enabled(q) && !exec_queue_suspended(q)) {
 		action[len++] = XE_GUC_ACTION_SCHED_CONTEXT_MODE_SET;
 		action[len++] = q->guc->id;
@@ -879,6 +1014,18 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job)
 	trace_xe_sched_job_run(job);
 
 	if (!killed_or_banned_or_wedged && !xe_sched_job_is_error(job)) {
+		if (xe_exec_queue_is_multi_queue_secondary(q)) {
+			struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
+
+			if (exec_queue_killed_or_banned_or_wedged(primary)) {
+				killed_or_banned_or_wedged = true;
+				goto run_job_out;
+			}
+
+			if (!exec_queue_registered(primary))
+				register_exec_queue(primary, GUC_CONTEXT_NORMAL);
+		}
+
 		if (!exec_queue_registered(q))
 			register_exec_queue(q, GUC_CONTEXT_NORMAL);
 		if (!job->skip_emit)
@@ -887,6 +1034,7 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job)
 		job->skip_emit = false;
 	}
 
+run_job_out:
 	/*
 	 * We don't care about job-fence ordering in LR VMs because these fences
 	 * are never exported; they are used solely to keep jobs on the pending
@@ -912,6 +1060,11 @@ int xe_guc_read_stopped(struct xe_guc *guc)
 	return atomic_read(&guc->submission_state.stopped);
 }
 
+static void handle_multi_queue_secondary_sched_done(struct xe_guc *guc,
+						    struct xe_exec_queue *q,
+						    u32 runnable_state);
+static void handle_deregister_done(struct xe_guc *guc, struct xe_exec_queue *q);
+
 #define MAKE_SCHED_CONTEXT_ACTION(q, enable_disable)			\
 	u32 action[] = {						\
 		XE_GUC_ACTION_SCHED_CONTEXT_MODE_SET,			\
@@ -925,7 +1078,9 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
 	MAKE_SCHED_CONTEXT_ACTION(q, DISABLE);
 	int ret;
 
-	set_min_preemption_timeout(guc, q);
+	if (!xe_exec_queue_is_multi_queue_secondary(q))
+		set_min_preemption_timeout(guc, q);
+
 	smp_rmb();
 	ret = wait_event_timeout(guc->ct.wq,
 				 (!exec_queue_pending_enable(q) &&
@@ -953,9 +1108,12 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
 	 * Reserve space for both G2H here as the 2nd G2H is sent from a G2H
 	 * handler and we are not allowed to reserved G2H space in handlers.
 	 */
-	xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
-		       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET +
-		       G2H_LEN_DW_DEREGISTER_CONTEXT, 2);
+	if (xe_exec_queue_is_multi_queue_secondary(q))
+		handle_multi_queue_secondary_sched_done(guc, q, 0);
+	else
+		xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
+			       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET +
+			       G2H_LEN_DW_DEREGISTER_CONTEXT, 2);
 }
 
 static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
@@ -1161,8 +1319,11 @@ static void enable_scheduling(struct xe_exec_queue *q)
 	set_exec_queue_enabled(q);
 	trace_xe_exec_queue_scheduling_enable(q);
 
-	xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
-		       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
+	if (xe_exec_queue_is_multi_queue_secondary(q))
+		handle_multi_queue_secondary_sched_done(guc, q, 1);
+	else
+		xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
+			       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
 
 	ret = wait_event_timeout(guc->ct.wq,
 				 !exec_queue_pending_enable(q) ||
@@ -1186,14 +1347,17 @@ static void disable_scheduling(struct xe_exec_queue *q, bool immediate)
 	xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q));
 	xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_disable(q));
 
-	if (immediate)
+	if (immediate && !xe_exec_queue_is_multi_queue_secondary(q))
 		set_min_preemption_timeout(guc, q);
 	clear_exec_queue_enabled(q);
 	set_exec_queue_pending_disable(q);
 	trace_xe_exec_queue_scheduling_disable(q);
 
-	xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
-		       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
+	if (xe_exec_queue_is_multi_queue_secondary(q))
+		handle_multi_queue_secondary_sched_done(guc, q, 0);
+	else
+		xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
+			       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
 }
 
 static void __deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q)
@@ -1211,8 +1375,11 @@ static void __deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q)
 	set_exec_queue_destroyed(q);
 	trace_xe_exec_queue_deregister(q);
 
-	xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
-		       G2H_LEN_DW_DEREGISTER_CONTEXT, 1);
+	if (xe_exec_queue_is_multi_queue_secondary(q))
+		handle_deregister_done(guc, q);
+	else
+		xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
+			       G2H_LEN_DW_DEREGISTER_CONTEXT, 1);
 }
 
 static enum drm_gpu_sched_stat
@@ -1655,6 +1822,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
 {
 	struct xe_gpu_scheduler *sched;
 	struct xe_guc *guc = exec_queue_to_guc(q);
+	struct workqueue_struct *submit_wq = NULL;
 	struct xe_guc_exec_queue *ge;
 	long timeout;
 	int err, i;
@@ -1675,8 +1843,20 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
 
 	timeout = (q->vm && xe_vm_in_lr_mode(q->vm)) ? MAX_SCHEDULE_TIMEOUT :
 		  msecs_to_jiffies(q->sched_props.job_timeout_ms);
+
+	/*
+	 * Use primary queue's submit_wq for all secondary queues of a
+	 * multi queue group. This serialization avoids any locking around
+	 * CGP synchronization with GuC.
+	 */
+	if (xe_exec_queue_is_multi_queue_secondary(q)) {
+		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
+
+		submit_wq = primary->guc->sched.base.submit_wq;
+	}
+
 	err = xe_sched_init(&ge->sched, &drm_sched_ops, &xe_sched_ops,
-			    NULL, xe_lrc_ring_size() / MAX_JOB_SIZE_BYTES, 64,
+			    submit_wq, xe_lrc_ring_size() / MAX_JOB_SIZE_BYTES, 64,
 			    timeout, guc_to_gt(guc)->ordered_wq, NULL,
 			    q->name, gt_to_xe(q->gt)->drm.dev);
 	if (err)
@@ -2413,7 +2593,11 @@ static void deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q)
 
 	trace_xe_exec_queue_deregister(q);
 
-	xe_guc_ct_send_g2h_handler(&guc->ct, action, ARRAY_SIZE(action));
+	if (xe_exec_queue_is_multi_queue_secondary(q))
+		handle_deregister_done(guc, q);
+	else
+		xe_guc_ct_send_g2h_handler(&guc->ct, action,
+					   ARRAY_SIZE(action));
 }
 
 static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q,
@@ -2463,6 +2647,16 @@ static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q,
 	}
 }
 
+static void handle_multi_queue_secondary_sched_done(struct xe_guc *guc,
+						    struct xe_exec_queue *q,
+						    u32 runnable_state)
+{
+	/* Take CT lock here as handle_sched_done() do send a h2g message */
+	mutex_lock(&guc->ct.lock);
+	handle_sched_done(guc, q, runnable_state);
+	mutex_unlock(&guc->ct.lock);
+}
+
 int xe_guc_sched_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
 {
 	struct xe_exec_queue *q;
@@ -2667,6 +2861,44 @@ int xe_guc_exec_queue_reset_failure_handler(struct xe_guc *guc, u32 *msg, u32 le
 	return 0;
 }
 
+/**
+ * xe_guc_exec_queue_cgp_sync_done_handler - CGP synchronization done handler
+ * @guc: guc
+ * @msg: message indicating CGP sync done
+ * @len: length of message
+ *
+ * Set multi queue group's sync_pending flag to false and wakeup anyone waiting
+ * for CGP synchronization to complete.
+ *
+ * Return: 0 on success, -EPROTO for malformed messages.
+ */
+int xe_guc_exec_queue_cgp_sync_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
+{
+	struct xe_device *xe = guc_to_xe(guc);
+	struct xe_exec_queue *q;
+	u32 guc_id = msg[0];
+
+	if (unlikely(len < 1)) {
+		drm_err(&xe->drm, "Invalid CGP_SYNC_DONE length %u", len);
+		return -EPROTO;
+	}
+
+	q = g2h_exec_queue_lookup(guc, guc_id);
+	if (unlikely(!q))
+		return -EPROTO;
+
+	if (!xe_exec_queue_is_multi_queue_primary(q)) {
+		drm_err(&xe->drm, "Unexpected CGP_SYNC_DONE response");
+		return -EPROTO;
+	}
+
+	/* Wakeup the serialized cgp update wait */
+	WRITE_ONCE(q->multi_queue.group->sync_pending, false);
+	wake_up_all(&guc->ct.wq);
+
+	return 0;
+}
+
 static void
 guc_exec_queue_wq_snapshot_capture(struct xe_exec_queue *q,
 				   struct xe_guc_submit_exec_queue_snapshot *snapshot)
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.h b/drivers/gpu/drm/xe/xe_guc_submit.h
index b49a2748ec46..abfa94bce391 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.h
+++ b/drivers/gpu/drm/xe/xe_guc_submit.h
@@ -34,6 +34,7 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg,
 					       u32 len);
 int xe_guc_exec_queue_reset_failure_handler(struct xe_guc *guc, u32 *msg, u32 len);
 int xe_guc_error_capture_handler(struct xe_guc *guc, u32 *msg, u32 len);
+int xe_guc_exec_queue_cgp_sync_done_handler(struct xe_guc *guc, u32 *msg, u32 len);
 
 struct xe_guc_submit_exec_queue_snapshot *
 xe_guc_exec_queue_snapshot_capture(struct xe_exec_queue *q);
-- 
2.43.0


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

* [PATCH v3 04/18] drm/xe/multi_queue: Add multi queue priority property
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (2 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 03/18] drm/xe/multi_queue: Add GuC " Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-21 22:57   ` Matthew Brost
  2025-11-21  3:51 ` [PATCH v3 05/18] drm/xe/multi_queue: Handle invalid exec queue property setting Niranjana Vishwanathapura
                   ` (19 subsequent siblings)
  23 siblings, 1 reply; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

Add support for queues of a multi queue group to set
their priority within the queue group by adding property
DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY.
This is the only other property supported by secondary
queues of a multi queue group, other than
DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE.

v2: Add kernel doc for enum xe_multi_queue_priority,
    Add assert for priority values, fix includes and
    declarations (Matt Brost)
v3: update uapi kernel-doc (Matt Brost)

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
---
 drivers/gpu/drm/xe/xe_exec_queue.c       | 17 +++++++++++++-
 drivers/gpu/drm/xe/xe_exec_queue_types.h | 16 +++++++++++++
 drivers/gpu/drm/xe/xe_guc_submit.c       |  1 +
 drivers/gpu/drm/xe/xe_lrc.c              | 29 ++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_lrc.h              |  3 +++
 include/uapi/drm/xe_drm.h                |  4 ++++
 6 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index 330b5103222c..6debcae8ce11 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -179,6 +179,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
 	INIT_LIST_HEAD(&q->multi_gt_link);
 	INIT_LIST_HEAD(&q->hw_engine_group_link);
 	INIT_LIST_HEAD(&q->pxp.link);
+	q->multi_queue.priority = XE_MULTI_QUEUE_PRIORITY_NORMAL;
 
 	q->sched_props.timeslice_us = hwe->eclass->sched_props.timeslice_us;
 	q->sched_props.preempt_timeout_us =
@@ -740,6 +741,17 @@ static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue
 	return xe_exec_queue_group_validate(xe, q, value);
 }
 
+static int exec_queue_set_multi_queue_priority(struct xe_device *xe, struct xe_exec_queue *q,
+					       u64 value)
+{
+	if (XE_IOCTL_DBG(xe, value > XE_MULTI_QUEUE_PRIORITY_HIGH))
+		return -EINVAL;
+
+	q->multi_queue.priority = value;
+
+	return 0;
+}
+
 typedef int (*xe_exec_queue_set_property_fn)(struct xe_device *xe,
 					     struct xe_exec_queue *q,
 					     u64 value);
@@ -749,6 +761,8 @@ static const xe_exec_queue_set_property_fn exec_queue_set_property_funcs[] = {
 	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE] = exec_queue_set_timeslice,
 	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE] = exec_queue_set_pxp_type,
 	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP] = exec_queue_set_multi_group,
+	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY] =
+							exec_queue_set_multi_queue_priority,
 };
 
 static int exec_queue_user_ext_set_property(struct xe_device *xe,
@@ -770,7 +784,8 @@ static int exec_queue_user_ext_set_property(struct xe_device *xe,
 	    XE_IOCTL_DBG(xe, ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY &&
 			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE &&
 			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE &&
-			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP))
+			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP &&
+			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY))
 		return -EINVAL;
 
 	idx = array_index_nospec(ext.property, ARRAY_SIZE(exec_queue_set_property_funcs));
diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
index b9da51ab7eaf..445ae4979c0c 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
@@ -32,6 +32,20 @@ enum xe_exec_queue_priority {
 	XE_EXEC_QUEUE_PRIORITY_COUNT
 };
 
+/**
+ * enum xe_multi_queue_priority - Multi Queue priority values
+ *
+ * The priority values of the queues within the multi queue group.
+ */
+enum xe_multi_queue_priority {
+	/** @XE_MULTI_QUEUE_PRIORITY_LOW: Priority low */
+	XE_MULTI_QUEUE_PRIORITY_LOW = 0,
+	/** @XE_MULTI_QUEUE_PRIORITY_NORMAL: Priority normal */
+	XE_MULTI_QUEUE_PRIORITY_NORMAL,
+	/** @XE_MULTI_QUEUE_PRIORITY_HIGH: Priority high */
+	XE_MULTI_QUEUE_PRIORITY_HIGH,
+};
+
 /**
  * struct xe_exec_queue_group - Execution multi queue group
  *
@@ -131,6 +145,8 @@ struct xe_exec_queue {
 	struct {
 		/** @multi_queue.group: Queue group information */
 		struct xe_exec_queue_group *group;
+		/** @multi_queue.priority: Queue priority within the multi-queue group */
+		enum xe_multi_queue_priority priority;
 		/** @multi_queue.pos: Position of queue within the multi-queue group */
 		u8 pos;
 		/** @multi_queue.valid: Queue belongs to a multi queue group */
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index c68739fd7592..8a75d0ed7ee9 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -638,6 +638,7 @@ static void xe_guc_exec_queue_group_cgp_sync(struct xe_guc *guc,
 		return;
 	}
 
+	xe_lrc_set_multi_queue_priority(q->lrc[0], q->multi_queue.priority);
 	xe_guc_exec_queue_group_cgp_update(xe, q);
 
 	WRITE_ONCE(group->sync_pending, true);
diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c
index b5083c99dd50..56836a5546d8 100644
--- a/drivers/gpu/drm/xe/xe_lrc.c
+++ b/drivers/gpu/drm/xe/xe_lrc.c
@@ -44,6 +44,11 @@
 #define LRC_INDIRECT_CTX_BO_SIZE		SZ_4K
 #define LRC_INDIRECT_RING_STATE_SIZE		SZ_4K
 
+#define LRC_PRIORITY				GENMASK_ULL(10, 9)
+#define LRC_PRIORITY_LOW			0
+#define LRC_PRIORITY_NORMAL			1
+#define LRC_PRIORITY_HIGH			2
+
 /*
  * Layout of the LRC and associated data allocated as
  * lrc->bo:
@@ -1386,6 +1391,30 @@ setup_indirect_ctx(struct xe_lrc *lrc, struct xe_hw_engine *hwe)
 	return 0;
 }
 
+static u8 xe_multi_queue_prio_to_lrc(struct xe_lrc *lrc, enum xe_multi_queue_priority priority)
+{
+	struct xe_device *xe = gt_to_xe(lrc->gt);
+
+	xe_assert(xe, (priority >= XE_MULTI_QUEUE_PRIORITY_LOW &&
+		       priority <= XE_MULTI_QUEUE_PRIORITY_HIGH));
+
+	/* xe_multi_queue_priority is directly mapped to LRC priority values */
+	return priority;
+}
+
+/**
+ * xe_lrc_set_multi_queue_priority() - Set multi queue priority in LRC
+ * @lrc: Logical Ring Context
+ * @priority: Multi queue priority of the exec queue
+ *
+ * Convert @priority to LRC multi queue priority and update the @lrc descriptor
+ */
+void xe_lrc_set_multi_queue_priority(struct xe_lrc *lrc, enum xe_multi_queue_priority priority)
+{
+	lrc->desc &= ~LRC_PRIORITY;
+	lrc->desc |= FIELD_PREP(LRC_PRIORITY, xe_multi_queue_prio_to_lrc(lrc, priority));
+}
+
 static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe,
 		       struct xe_vm *vm, u32 ring_size, u16 msix_vec,
 		       u32 init_flags)
diff --git a/drivers/gpu/drm/xe/xe_lrc.h b/drivers/gpu/drm/xe/xe_lrc.h
index 2fb628da5c43..569ca380676e 100644
--- a/drivers/gpu/drm/xe/xe_lrc.h
+++ b/drivers/gpu/drm/xe/xe_lrc.h
@@ -13,6 +13,7 @@ struct drm_printer;
 struct xe_bb;
 struct xe_device;
 struct xe_exec_queue;
+enum xe_multi_queue_priority;
 enum xe_engine_class;
 struct xe_gt;
 struct xe_hw_engine;
@@ -133,6 +134,8 @@ void xe_lrc_dump_default(struct drm_printer *p,
 
 u32 *xe_lrc_emit_hwe_state_instructions(struct xe_exec_queue *q, u32 *cs);
 
+void xe_lrc_set_multi_queue_priority(struct xe_lrc *lrc, enum xe_multi_queue_priority priority);
+
 struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc);
 void xe_lrc_snapshot_capture_delayed(struct xe_lrc_snapshot *snapshot);
 void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer *p);
diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
index 4de21e0a4fcf..240eeea99cb0 100644
--- a/include/uapi/drm/xe_drm.h
+++ b/include/uapi/drm/xe_drm.h
@@ -1260,6 +1260,9 @@ struct drm_xe_vm_bind {
  *    queue's exec_queue_id is specified in the lower 32 bits of the 'value' field.
  *    All the other non-relevant bits of extension's 'value' field while adding the
  *    primary or the secondary queues of the group must be set to 0.
+ *  - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY - Set the queue
+ *    priority within the multi-queue group. Current valid priority values are 0–2
+ *    (default is 1), with higher values indicating higher priority.
  *
  * The example below shows how to use @drm_xe_exec_queue_create to create
  * a simple exec_queue (no parallel submission) of class
@@ -1302,6 +1305,7 @@ struct drm_xe_exec_queue_create {
 #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE		2
 #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP		3
 #define     DRM_XE_MULTI_GROUP_CREATE				(1ull << 63)
+#define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY	4
 	/** @extensions: Pointer to the first extension struct, if any */
 	__u64 extensions;
 
-- 
2.43.0


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

* [PATCH v3 05/18] drm/xe/multi_queue: Handle invalid exec queue property setting
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (3 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 04/18] drm/xe/multi_queue: Add multi queue priority property Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-21  3:51 ` [PATCH v3 06/18] drm/xe/multi_queue: Add exec_queue set_property ioctl support Niranjana Vishwanathapura
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

Only MULTI_QUEUE_PRIORITY property is valid for secondary queues of a
multi queue group. MULTI_QUEUE_PRIORITY only applies to multi queue group
queues. Detect invalid user queue property setting and return error.

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_exec_queue.c | 66 ++++++++++++++++++++++++++----
 1 file changed, 57 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index 6debcae8ce11..b8a3fc7d6944 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -62,7 +62,7 @@ enum xe_exec_queue_sched_prop {
 };
 
 static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue *q,
-				      u64 extensions, int ext_number);
+				      u64 extensions);
 
 static void xe_exec_queue_group_cleanup(struct xe_exec_queue *q)
 {
@@ -208,7 +208,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
 		 * may set q->usm, must come before xe_lrc_create(),
 		 * may overwrite q->sched_props, must come before q->ops->init()
 		 */
-		err = exec_queue_user_extensions(xe, q, extensions, 0);
+		err = exec_queue_user_extensions(xe, q, extensions);
 		if (err) {
 			__xe_exec_queue_free(q);
 			return ERR_PTR(err);
@@ -765,9 +765,35 @@ static const xe_exec_queue_set_property_fn exec_queue_set_property_funcs[] = {
 							exec_queue_set_multi_queue_priority,
 };
 
+static int exec_queue_user_ext_check(struct xe_exec_queue *q, u64 properties)
+{
+	u64 secondary_queue_valid_props = BIT_ULL(DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP) |
+				  BIT_ULL(DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY);
+
+	/*
+	 * Only MULTI_QUEUE_PRIORITY property is valid for secondary queues of a
+	 * multi-queue group.
+	 */
+	if (xe_exec_queue_is_multi_queue_secondary(q) &&
+	    properties & ~secondary_queue_valid_props)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int exec_queue_user_ext_check_final(struct xe_exec_queue *q, u64 properties)
+{
+	/* MULTI_QUEUE_PRIORITY only applies to multi-queue group queues */
+	if ((properties & BIT_ULL(DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY)) &&
+	    !(properties & BIT_ULL(DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP)))
+		return -EINVAL;
+
+	return 0;
+}
+
 static int exec_queue_user_ext_set_property(struct xe_device *xe,
 					    struct xe_exec_queue *q,
-					    u64 extension)
+					    u64 extension, u64 *properties)
 {
 	u64 __user *address = u64_to_user_ptr(extension);
 	struct drm_xe_ext_set_property ext;
@@ -792,20 +818,25 @@ static int exec_queue_user_ext_set_property(struct xe_device *xe,
 	if (!exec_queue_set_property_funcs[idx])
 		return -EINVAL;
 
+	*properties |= BIT_ULL(idx);
+	err = exec_queue_user_ext_check(q, *properties);
+	if (XE_IOCTL_DBG(xe, err))
+		return err;
+
 	return exec_queue_set_property_funcs[idx](xe, q, ext.value);
 }
 
 typedef int (*xe_exec_queue_user_extension_fn)(struct xe_device *xe,
 					       struct xe_exec_queue *q,
-					       u64 extension);
+					       u64 extension, u64 *properties);
 
 static const xe_exec_queue_user_extension_fn exec_queue_user_extension_funcs[] = {
 	[DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY] = exec_queue_user_ext_set_property,
 };
 
 #define MAX_USER_EXTENSIONS	16
-static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue *q,
-				      u64 extensions, int ext_number)
+static int __exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue *q,
+					u64 extensions, int ext_number, u64 *properties)
 {
 	u64 __user *address = u64_to_user_ptr(extensions);
 	struct drm_xe_user_extension ext;
@@ -826,13 +857,30 @@ static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue
 
 	idx = array_index_nospec(ext.name,
 				 ARRAY_SIZE(exec_queue_user_extension_funcs));
-	err = exec_queue_user_extension_funcs[idx](xe, q, extensions);
+	err = exec_queue_user_extension_funcs[idx](xe, q, extensions, properties);
 	if (XE_IOCTL_DBG(xe, err))
 		return err;
 
 	if (ext.next_extension)
-		return exec_queue_user_extensions(xe, q, ext.next_extension,
-						  ++ext_number);
+		return __exec_queue_user_extensions(xe, q, ext.next_extension,
+						    ++ext_number, properties);
+
+	return 0;
+}
+
+static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue *q,
+				      u64 extensions)
+{
+	u64 properties = 0;
+	int err;
+
+	err = __exec_queue_user_extensions(xe, q, extensions, 0, &properties);
+	if (XE_IOCTL_DBG(xe, err))
+		return err;
+
+	err = exec_queue_user_ext_check_final(q, properties);
+	if (XE_IOCTL_DBG(xe, err))
+		return err;
 
 	if (xe_exec_queue_is_multi_queue_primary(q)) {
 		err = xe_exec_queue_group_init(xe, q);
-- 
2.43.0


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

* [PATCH v3 06/18] drm/xe/multi_queue: Add exec_queue set_property ioctl support
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (4 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 05/18] drm/xe/multi_queue: Handle invalid exec queue property setting Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-21  3:51 ` [PATCH v3 07/18] drm/xe/multi_queue: Add support for multi queue dynamic priority change Niranjana Vishwanathapura
                   ` (17 subsequent siblings)
  23 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

This patch adds support for exec_queue set_property ioctl.
It is derived from the original work which is part of
https://patchwork.freedesktop.org/series/112188/

Currently only DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY
property can be dynamically set.

v2: Check for and update kernel-doc which property this ioctl
    supports (Matt Brost)

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Pallavi Mishra <pallavi.mishra@intel.com>
Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_device.c     |  2 ++
 drivers/gpu/drm/xe/xe_exec_queue.c | 35 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_exec_queue.h |  2 ++
 include/uapi/drm/xe_drm.h          | 26 ++++++++++++++++++++++
 4 files changed, 65 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 92f883dd8877..037206c8b543 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -207,6 +207,8 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(XE_VM_QUERY_MEM_RANGE_ATTRS, xe_vm_query_vmas_attrs_ioctl,
 			  DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(XE_EXEC_QUEUE_SET_PROPERTY, xe_exec_queue_set_property_ioctl,
+			  DRM_RENDER_ALLOW),
 };
 
 static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index b8a3fc7d6944..2a592a183ccc 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -765,6 +765,41 @@ static const xe_exec_queue_set_property_fn exec_queue_set_property_funcs[] = {
 							exec_queue_set_multi_queue_priority,
 };
 
+int xe_exec_queue_set_property_ioctl(struct drm_device *dev, void *data,
+				     struct drm_file *file)
+{
+	struct xe_device *xe = to_xe_device(dev);
+	struct xe_file *xef = to_xe_file(file);
+	struct drm_xe_exec_queue_set_property *args = data;
+	struct xe_exec_queue *q;
+	int ret;
+	u32 idx;
+
+	if (XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]))
+		return -EINVAL;
+
+	if (XE_IOCTL_DBG(xe, args->property !=
+			 DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY))
+		return -EINVAL;
+
+	q = xe_exec_queue_lookup(xef, args->exec_queue_id);
+	if (XE_IOCTL_DBG(xe, !q))
+		return -ENOENT;
+
+	idx = array_index_nospec(args->property,
+				 ARRAY_SIZE(exec_queue_set_property_funcs));
+	ret = exec_queue_set_property_funcs[idx](xe, q, args->value);
+	if (XE_IOCTL_DBG(xe, ret))
+		goto err_post_lookup;
+
+	xe_exec_queue_put(q);
+	return 0;
+
+ err_post_lookup:
+	xe_exec_queue_put(q);
+	return ret;
+}
+
 static int exec_queue_user_ext_check(struct xe_exec_queue *q, u64 properties)
 {
 	u64 secondary_queue_valid_props = BIT_ULL(DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP) |
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.h b/drivers/gpu/drm/xe/xe_exec_queue.h
index e6daa40003f2..ffcc1feb879e 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue.h
@@ -125,6 +125,8 @@ int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file);
 int xe_exec_queue_get_property_ioctl(struct drm_device *dev, void *data,
 				     struct drm_file *file);
+int xe_exec_queue_set_property_ioctl(struct drm_device *dev, void *data,
+				     struct drm_file *file);
 enum xe_exec_queue_priority xe_exec_queue_device_get_max_priority(struct xe_device *xe);
 
 void xe_exec_queue_last_fence_put(struct xe_exec_queue *e, struct xe_vm *vm);
diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
index 240eeea99cb0..71a851615876 100644
--- a/include/uapi/drm/xe_drm.h
+++ b/include/uapi/drm/xe_drm.h
@@ -106,6 +106,7 @@ extern "C" {
 #define DRM_XE_OBSERVATION		0x0b
 #define DRM_XE_MADVISE			0x0c
 #define DRM_XE_VM_QUERY_MEM_RANGE_ATTRS	0x0d
+#define DRM_XE_EXEC_QUEUE_SET_PROPERTY	0x0e
 
 /* Must be kept compact -- no holes */
 
@@ -123,6 +124,7 @@ extern "C" {
 #define DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct drm_xe_observation_param)
 #define DRM_IOCTL_XE_MADVISE			DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, struct drm_xe_madvise)
 #define DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_QUERY_MEM_RANGE_ATTRS, struct drm_xe_vm_query_mem_range_attr)
+#define DRM_IOCTL_XE_EXEC_QUEUE_SET_PROPERTY	DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC_QUEUE_SET_PROPERTY, struct drm_xe_exec_queue_set_property)
 
 /**
  * DOC: Xe IOCTL Extensions
@@ -2287,6 +2289,30 @@ struct drm_xe_vm_query_mem_range_attr {
 
 };
 
+/**
+ * struct drm_xe_exec_queue_set_property - exec queue set property
+ *
+ * Sets execution queue properties dynamically.
+ * Currently only %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY
+ * property can be dynamically set.
+ */
+struct drm_xe_exec_queue_set_property {
+	/** @extensions: Pointer to the first extension struct, if any */
+	__u64 extensions;
+
+	/** @exec_queue_id: Exec queue ID */
+	__u32 exec_queue_id;
+
+	/** @property: property to set */
+	__u32 property;
+
+	/** @value: property value */
+	__u64 value;
+
+	/** @reserved: Reserved */
+	__u64 reserved[2];
+};
+
 #if defined(__cplusplus)
 }
 #endif
-- 
2.43.0


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

* [PATCH v3 07/18] drm/xe/multi_queue: Add support for multi queue dynamic priority change
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (5 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 06/18] drm/xe/multi_queue: Add exec_queue set_property ioctl support Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-21  3:51 ` [PATCH v3 08/18] drm/xe/multi_queue: Add multi queue information to guc_info dump Niranjana Vishwanathapura
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

Support dynamic priority change for multi queue group queues via
exec queue set_property ioctl. Issue CGP_SYNC command to GuC through
the drm scheduler message interface for priority to take effect.

v2: Move is_multi_queue check to exec_queue layer and assert
    is_multi_queue being set in guc submission layer (Matt Brost)
v3: Assert CGP_SYNC message length is valid (Matt Brost)

Signed-off-by: Pallavi Mishra <pallavi.mishra@intel.com>
Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_exec_queue.c       | 11 ++++-
 drivers/gpu/drm/xe/xe_exec_queue_types.h |  3 ++
 drivers/gpu/drm/xe/xe_guc_submit.c       | 57 ++++++++++++++++++++++--
 3 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index 2a592a183ccc..cdc044d3c96c 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -747,9 +747,16 @@ static int exec_queue_set_multi_queue_priority(struct xe_device *xe, struct xe_e
 	if (XE_IOCTL_DBG(xe, value > XE_MULTI_QUEUE_PRIORITY_HIGH))
 		return -EINVAL;
 
-	q->multi_queue.priority = value;
+	/* For queue creation time (!q->xef) setting, just store the priority value */
+	if (!q->xef) {
+		q->multi_queue.priority = value;
+		return 0;
+	}
 
-	return 0;
+	if (!xe_exec_queue_is_multi_queue(q))
+		return -EINVAL;
+
+	return q->ops->set_multi_queue_priority(q, value);
 }
 
 typedef int (*xe_exec_queue_set_property_fn)(struct xe_device *xe,
diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
index 445ae4979c0c..cafb3ba9a123 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
@@ -257,6 +257,9 @@ struct xe_exec_queue_ops {
 	int (*set_timeslice)(struct xe_exec_queue *q, u32 timeslice_us);
 	/** @set_preempt_timeout: Set preemption timeout for exec queue */
 	int (*set_preempt_timeout)(struct xe_exec_queue *q, u32 preempt_timeout_us);
+	/** @set_multi_queue_priority: Set multi queue priority */
+	int (*set_multi_queue_priority)(struct xe_exec_queue *q,
+					enum xe_multi_queue_priority priority);
 	/**
 	 * @suspend: Suspend exec queue from executing, allowed to be called
 	 * multiple times in a row before resume with the caveat that
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 8a75d0ed7ee9..54636d3a5eb2 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -1775,10 +1775,34 @@ static void __guc_exec_queue_process_msg_resume(struct xe_sched_msg *msg)
 	}
 }
 
-#define CLEANUP		1	/* Non-zero values to catch uninitialized msg */
-#define SET_SCHED_PROPS	2
-#define SUSPEND		3
-#define RESUME		4
+static void __guc_exec_queue_process_msg_set_multi_queue_priority(struct xe_sched_msg *msg)
+{
+	struct xe_exec_queue *q = msg->private_data;
+
+	if (guc_exec_queue_allowed_to_change_state(q)) {
+#define MAX_MULTI_QUEUE_CGP_SYNC_SIZE        (2)
+		struct xe_guc *guc = exec_queue_to_guc(q);
+		struct xe_exec_queue_group *group = q->multi_queue.group;
+		u32 action[MAX_MULTI_QUEUE_CGP_SYNC_SIZE];
+		int len = 0;
+
+		action[len++] = XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC;
+		action[len++] = group->primary->guc->id;
+
+		xe_gt_assert(guc_to_gt(guc), len <= MAX_MULTI_QUEUE_CGP_SYNC_SIZE);
+#undef MAX_MULTI_QUEUE_CGP_SYNC_SIZE
+
+		xe_guc_exec_queue_group_cgp_sync(guc, q, action, len);
+	}
+
+	kfree(msg);
+}
+
+#define CLEANUP				1	/* Non-zero values to catch uninitialized msg */
+#define SET_SCHED_PROPS			2
+#define SUSPEND				3
+#define RESUME				4
+#define SET_MULTI_QUEUE_PRIORITY	5
 #define OPCODE_MASK	0xf
 #define MSG_LOCKED	BIT(8)
 #define MSG_HEAD	BIT(9)
@@ -1802,6 +1826,9 @@ static void guc_exec_queue_process_msg(struct xe_sched_msg *msg)
 	case RESUME:
 		__guc_exec_queue_process_msg_resume(msg);
 		break;
+	case SET_MULTI_QUEUE_PRIORITY:
+		__guc_exec_queue_process_msg_set_multi_queue_priority(msg);
+		break;
 	default:
 		XE_WARN_ON("Unknown message type");
 	}
@@ -2018,6 +2045,27 @@ static int guc_exec_queue_set_preempt_timeout(struct xe_exec_queue *q,
 	return 0;
 }
 
+static int guc_exec_queue_set_multi_queue_priority(struct xe_exec_queue *q,
+						   enum xe_multi_queue_priority priority)
+{
+	struct xe_sched_msg *msg;
+
+	xe_gt_assert(guc_to_gt(exec_queue_to_guc(q)), xe_exec_queue_is_multi_queue(q));
+
+	if (q->multi_queue.priority == priority ||
+	    exec_queue_killed_or_banned_or_wedged(q))
+		return 0;
+
+	msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	q->multi_queue.priority = priority;
+	guc_exec_queue_add_msg(q, msg, SET_MULTI_QUEUE_PRIORITY);
+
+	return 0;
+}
+
 static int guc_exec_queue_suspend(struct xe_exec_queue *q)
 {
 	struct xe_gpu_scheduler *sched = &q->guc->sched;
@@ -2109,6 +2157,7 @@ static const struct xe_exec_queue_ops guc_exec_queue_ops = {
 	.set_priority = guc_exec_queue_set_priority,
 	.set_timeslice = guc_exec_queue_set_timeslice,
 	.set_preempt_timeout = guc_exec_queue_set_preempt_timeout,
+	.set_multi_queue_priority = guc_exec_queue_set_multi_queue_priority,
 	.suspend = guc_exec_queue_suspend,
 	.suspend_wait = guc_exec_queue_suspend_wait,
 	.resume = guc_exec_queue_resume,
-- 
2.43.0


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

* [PATCH v3 08/18] drm/xe/multi_queue: Add multi queue information to guc_info dump
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (6 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 07/18] drm/xe/multi_queue: Add support for multi queue dynamic priority change Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-21  3:51 ` [PATCH v3 09/18] drm/xe/multi_queue: Handle tearing down of a multi queue Niranjana Vishwanathapura
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

Dump multi queue specific information in the guc exec queue
dump.

v2: Move multi queue related fields inside the multi_queue
    sub-structure (Matt Brost)

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_guc_submit.c       | 10 ++++++++++
 drivers/gpu/drm/xe/xe_guc_submit_types.h | 13 +++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 54636d3a5eb2..ce870a119800 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -3048,6 +3048,11 @@ xe_guc_exec_queue_snapshot_capture(struct xe_exec_queue *q)
 	if (snapshot->parallel_execution)
 		guc_exec_queue_wq_snapshot_capture(q, snapshot);
 
+	if (xe_exec_queue_is_multi_queue(q)) {
+		snapshot->multi_queue.valid = true;
+		snapshot->multi_queue.primary = xe_exec_queue_multi_queue_primary(q)->guc->id;
+		snapshot->multi_queue.pos = q->multi_queue.pos;
+	}
 	spin_lock(&sched->base.job_list_lock);
 	snapshot->pending_list_size = list_count_nodes(&sched->base.pending_list);
 	snapshot->pending_list = kmalloc_array(snapshot->pending_list_size,
@@ -3130,6 +3135,11 @@ xe_guc_exec_queue_snapshot_print(struct xe_guc_submit_exec_queue_snapshot *snaps
 	if (snapshot->parallel_execution)
 		guc_exec_queue_wq_snapshot_print(snapshot, p);
 
+	if (snapshot->multi_queue.valid) {
+		drm_printf(p, "\tMulti queue primary GuC ID: %d\n", snapshot->multi_queue.primary);
+		drm_printf(p, "\tMulti queue position: %d\n", snapshot->multi_queue.pos);
+	}
+
 	for (i = 0; snapshot->pending_list && i < snapshot->pending_list_size;
 	     i++)
 		drm_printf(p, "\tJob: seqno=%d, fence=%d, finished=%d\n",
diff --git a/drivers/gpu/drm/xe/xe_guc_submit_types.h b/drivers/gpu/drm/xe/xe_guc_submit_types.h
index dc7456c34583..25e29e85502c 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit_types.h
+++ b/drivers/gpu/drm/xe/xe_guc_submit_types.h
@@ -135,6 +135,19 @@ struct xe_guc_submit_exec_queue_snapshot {
 		u32 wq[WQ_SIZE / sizeof(u32)];
 	} parallel;
 
+	/** @multi_queue: snapshot of the multi queue information */
+	struct {
+		/**
+		 * @multi_queue.primary: GuC id of the primary exec queue
+		 * of the multi queue group.
+		 */
+		u32 primary;
+		/** @multi_queue.pos: Position of the exec queue within the multi queue group */
+		u8 pos;
+		/** @valid: The exec queue is part of a multi queue group */
+		bool valid;
+	} multi_queue;
+
 	/** @pending_list_size: Size of the pending list snapshot array */
 	int pending_list_size;
 	/** @pending_list: snapshot of the pending list info */
-- 
2.43.0


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

* [PATCH v3 09/18] drm/xe/multi_queue: Handle tearing down of a multi queue
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (7 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 08/18] drm/xe/multi_queue: Add multi queue information to guc_info dump Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-21 23:03   ` Matthew Brost
  2025-11-22  5:47   ` Matthew Brost
  2025-11-21  3:51 ` [PATCH v3 10/18] drm/xe/multi_queue: Set QUEUE_DRAIN_MODE for Multi Queue batches Niranjana Vishwanathapura
                   ` (14 subsequent siblings)
  23 siblings, 2 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

As all queues of a multi queue group use the primary queue of the group
to interface with GuC. Hence there is a dependency between the queues of
the group. So, when primary queue of a multi queue group is cleaned up,
also trigger a cleanup of the secondary queues also. During cleanup, stop
and re-start submission for all queues of a multi queue group to avoid
any submission happening in parallel when a queue is being cleaned up.

v2: Initialize group->list_lock, add fs_reclaim dependency, remove
    unwanted secondary queues cleanup (Matt Brost)
v3: Properly handle cleanup of multi-queue group (Matt Brost)

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
---
 drivers/gpu/drm/xe/xe_exec_queue.c       |  10 ++
 drivers/gpu/drm/xe/xe_exec_queue_types.h |   6 +
 drivers/gpu/drm/xe/xe_guc_submit.c       | 154 ++++++++++++++++++-----
 3 files changed, 142 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index cdc044d3c96c..ab161b74fef0 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -87,6 +87,7 @@ static void xe_exec_queue_group_cleanup(struct xe_exec_queue *q)
 		xe_lrc_put(lrc);
 
 	xa_destroy(&group->xa);
+	mutex_destroy(&group->list_lock);
 	xe_bo_unpin_map_no_vm(group->cgp_bo);
 	kfree(group);
 }
@@ -627,9 +628,18 @@ static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue *
 
 	group->primary = q;
 	group->cgp_bo = bo;
+	INIT_LIST_HEAD(&group->list);
 	xa_init_flags(&group->xa, XA_FLAGS_ALLOC1);
+	mutex_init(&group->list_lock);
 	q->multi_queue.group = group;
 
+	/* group->list_lock is used in submission backend */
+	if (!IS_ENABLED(CONFIG_LOCKDEP)) {
+		fs_reclaim_acquire(GFP_KERNEL);
+		might_lock(&group->list_lock);
+		fs_reclaim_release(GFP_KERNEL);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
index cafb3ba9a123..5721fb4bad1a 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
@@ -58,6 +58,10 @@ struct xe_exec_queue_group {
 	struct xe_bo *cgp_bo;
 	/** @xa: xarray to store LRCs */
 	struct xarray xa;
+	/** @list: List of all secondary queues in the group */
+	struct list_head list;
+	/** @list_lock: Secondary queue list lock */
+	struct mutex list_lock;
 	/** @sync_pending: CGP_SYNC_DONE g2h response pending */
 	bool sync_pending;
 };
@@ -145,6 +149,8 @@ struct xe_exec_queue {
 	struct {
 		/** @multi_queue.group: Queue group information */
 		struct xe_exec_queue_group *group;
+		/** @multi_queue.link: Link into group's secondary queues list */
+		struct list_head link;
 		/** @multi_queue.priority: Queue priority within the multi-queue group */
 		enum xe_multi_queue_priority priority;
 		/** @multi_queue.pos: Position of queue within the multi-queue group */
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index ce870a119800..2e5fff7ad69b 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -577,6 +577,45 @@ static bool vf_recovery(struct xe_guc *guc)
 	return xe_gt_recovery_pending(guc_to_gt(guc));
 }
 
+static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
+{
+	struct xe_guc *guc = exec_queue_to_guc(q);
+	struct xe_device *xe = guc_to_xe(guc);
+
+	/** to wakeup xe_wait_user_fence ioctl if exec queue is reset */
+	wake_up_all(&xe->ufence_wq);
+
+	if (xe_exec_queue_is_lr(q))
+		queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr);
+	else
+		xe_sched_tdr_queue_imm(&q->guc->sched);
+}
+
+static void xe_guc_exec_queue_reset_trigger_cleanup(struct xe_exec_queue *q)
+{
+	if (xe_exec_queue_is_multi_queue(q)) {
+		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
+		struct xe_exec_queue_group *group = q->multi_queue.group;
+		struct xe_exec_queue *eq;
+
+		set_exec_queue_reset(primary);
+		if (!exec_queue_banned(primary) && !exec_queue_check_timeout(primary))
+			xe_guc_exec_queue_trigger_cleanup(primary);
+
+		mutex_lock(&group->list_lock);
+		list_for_each_entry(eq, &group->list, multi_queue.link) {
+			set_exec_queue_reset(eq);
+			if (!exec_queue_banned(eq) && !exec_queue_check_timeout(eq))
+				xe_guc_exec_queue_trigger_cleanup(eq);
+		}
+		mutex_unlock(&group->list_lock);
+	} else {
+		set_exec_queue_reset(q);
+		if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
+			xe_guc_exec_queue_trigger_cleanup(q);
+	}
+}
+
 #define parallel_read(xe_, map_, field_) \
 	xe_map_rd_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
 			field_)
@@ -939,6 +978,50 @@ static void wq_item_append(struct xe_exec_queue *q)
 	parallel_write(xe, map, wq_desc.tail, q->guc->wqi_tail);
 }
 
+static void xe_guc_exec_queue_submission_start(struct xe_exec_queue *q)
+{
+	/*
+	 * If the exec queue is part of a multi queue group, then start submission
+	 * on all queues of the multi queue group.
+	 */
+	if (xe_exec_queue_is_multi_queue(q)) {
+		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
+		struct xe_exec_queue_group *group = q->multi_queue.group;
+		struct xe_exec_queue *eq;
+
+		xe_sched_submission_start(&primary->guc->sched);
+
+		mutex_lock(&group->list_lock);
+		list_for_each_entry(eq, &group->list, multi_queue.link)
+			xe_sched_submission_start(&eq->guc->sched);
+		mutex_unlock(&group->list_lock);
+	} else {
+		xe_sched_submission_start(&q->guc->sched);
+	}
+}
+
+static void xe_guc_exec_queue_submission_stop(struct xe_exec_queue *q)
+{
+	/*
+	 * If the exec queue is part of a multi queue group, then stop submission
+	 * on all queues of the multi queue group.
+	 */
+	if (xe_exec_queue_is_multi_queue(q)) {
+		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
+		struct xe_exec_queue_group *group = q->multi_queue.group;
+		struct xe_exec_queue *eq;
+
+		xe_sched_submission_stop(&primary->guc->sched);
+
+		mutex_lock(&group->list_lock);
+		list_for_each_entry(eq, &group->list, multi_queue.link)
+			xe_sched_submission_stop(&eq->guc->sched);
+		mutex_unlock(&group->list_lock);
+	} else {
+		xe_sched_submission_stop(&q->guc->sched);
+	}
+}
+
 #define RESUME_PENDING	~0x0ull
 static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job)
 {
@@ -1117,20 +1200,6 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
 			       G2H_LEN_DW_DEREGISTER_CONTEXT, 2);
 }
 
-static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
-{
-	struct xe_guc *guc = exec_queue_to_guc(q);
-	struct xe_device *xe = guc_to_xe(guc);
-
-	/** to wakeup xe_wait_user_fence ioctl if exec queue is reset */
-	wake_up_all(&xe->ufence_wq);
-
-	if (xe_exec_queue_is_lr(q))
-		queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr);
-	else
-		xe_sched_tdr_queue_imm(&q->guc->sched);
-}
-
 /**
  * xe_guc_submit_wedge() - Wedge GuC submission
  * @guc: the GuC object
@@ -1204,8 +1273,12 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
 	if (!exec_queue_killed(q))
 		wedged = guc_submit_hint_wedged(exec_queue_to_guc(q));
 
-	/* Kill the run_job / process_msg entry points */
-	xe_sched_submission_stop(sched);
+	/*
+	 * Kill the run_job / process_msg entry points.
+	 * As this function is serialized across exec queues, it is safe to
+	 * stop and restart submission on all queues of a multi queue group.
+	 */
+	xe_guc_exec_queue_submission_stop(q);
 
 	/*
 	 * Engine state now mostly stable, disable scheduling / deregister if
@@ -1241,7 +1314,7 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
 				   q->guc->id);
 			xe_devcoredump(q, NULL, "Schedule disable failed to respond, guc_id=%d\n",
 				       q->guc->id);
-			xe_sched_submission_start(sched);
+			xe_guc_exec_queue_submission_start(q);
 			xe_gt_reset_async(q->gt);
 			return;
 		}
@@ -1252,7 +1325,7 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
 
 	xe_hw_fence_irq_stop(q->fence_irq);
 
-	xe_sched_submission_start(sched);
+	xe_guc_exec_queue_submission_start(q);
 
 	spin_lock(&sched->base.job_list_lock);
 	list_for_each_entry(job, &sched->base.pending_list, drm.list)
@@ -1410,8 +1483,12 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
 	    vf_recovery(guc))
 		return DRM_GPU_SCHED_STAT_NO_HANG;
 
-	/* Kill the run_job entry point */
-	xe_sched_submission_stop(sched);
+	/*
+	 * Kill the run_job entry point.
+	 * As this function is serialized across exec queues, it is safe to
+	 * stop and restart submission on all queues of a multi queue group.
+	 */
+	xe_guc_exec_queue_submission_stop(q);
 
 	/* Must check all state after stopping scheduler */
 	skip_timeout_check = exec_queue_reset(q) ||
@@ -1568,7 +1645,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
 	 * fences that are complete
 	 */
 	xe_sched_add_pending_job(sched, job);
-	xe_sched_submission_start(sched);
+	xe_guc_exec_queue_submission_start(q);
 
 	xe_guc_exec_queue_trigger_cleanup(q);
 
@@ -1592,7 +1669,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
 	 * but there is not currently an easy way to do in DRM scheduler. With
 	 * some thought, do this in a follow up.
 	 */
-	xe_sched_submission_start(sched);
+	xe_guc_exec_queue_submission_start(q);
 handle_vf_resume:
 	return DRM_GPU_SCHED_STAT_NO_HANG;
 }
@@ -1623,6 +1700,14 @@ static void __guc_exec_queue_destroy_async(struct work_struct *w)
 	guard(xe_pm_runtime)(guc_to_xe(guc));
 	trace_xe_exec_queue_destroy(q);
 
+	if (xe_exec_queue_is_multi_queue_secondary(q)) {
+		struct xe_exec_queue_group *group = q->multi_queue.group;
+
+		mutex_lock(&group->list_lock);
+		list_del(&q->multi_queue.link);
+		mutex_unlock(&group->list_lock);
+	}
+
 	if (xe_exec_queue_is_lr(q))
 		cancel_work_sync(&ge->lr_tdr);
 	/* Confirm no work left behind accessing device structures */
@@ -1913,6 +1998,19 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
 
 	xe_exec_queue_assign_name(q, q->guc->id);
 
+	/*
+	 * Maintain secondary queues of the multi queue group in a list
+	 * for handling dependencies across the queues in the group.
+	 */
+	if (xe_exec_queue_is_multi_queue_secondary(q)) {
+		struct xe_exec_queue_group *group = q->multi_queue.group;
+
+		INIT_LIST_HEAD(&q->multi_queue.link);
+		mutex_lock(&group->list_lock);
+		list_add_tail(&q->multi_queue.link, &group->list);
+		mutex_unlock(&group->list_lock);
+	}
+
 	trace_xe_exec_queue_create(q);
 
 	return 0;
@@ -2140,6 +2238,10 @@ static void guc_exec_queue_resume(struct xe_exec_queue *q)
 
 static bool guc_exec_queue_reset_status(struct xe_exec_queue *q)
 {
+	if (xe_exec_queue_is_multi_queue_secondary(q) &&
+	    guc_exec_queue_reset_status(xe_exec_queue_multi_queue_primary(q)))
+		return true;
+
 	return exec_queue_reset(q) || exec_queue_killed_or_banned_or_wedged(q);
 }
 
@@ -2801,9 +2903,7 @@ int xe_guc_exec_queue_reset_handler(struct xe_guc *guc, u32 *msg, u32 len)
 	 * jobs by setting timeout of the job to the minimum value kicking
 	 * guc_exec_queue_timedout_job.
 	 */
-	set_exec_queue_reset(q);
-	if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
-		xe_guc_exec_queue_trigger_cleanup(q);
+	xe_guc_exec_queue_reset_trigger_cleanup(q);
 
 	return 0;
 }
@@ -2882,9 +2982,7 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg,
 	trace_xe_exec_queue_memory_cat_error(q);
 
 	/* Treat the same as engine reset */
-	set_exec_queue_reset(q);
-	if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
-		xe_guc_exec_queue_trigger_cleanup(q);
+	xe_guc_exec_queue_reset_trigger_cleanup(q);
 
 	return 0;
 }
-- 
2.43.0


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

* [PATCH v3 10/18] drm/xe/multi_queue: Set QUEUE_DRAIN_MODE for Multi Queue batches
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (8 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 09/18] drm/xe/multi_queue: Handle tearing down of a multi queue Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-24 18:49   ` Matt Roper
  2025-11-21  3:51 ` [PATCH v3 11/18] drm/xe/multi_queue: Handle CGP context error Niranjana Vishwanathapura
                   ` (13 subsequent siblings)
  23 siblings, 1 reply; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

To properly support soft light restore between batches
being arbitrated at the CFEG, PIPE_CONTROL instructions
have a new bit in the first DW, QUEUE_DRAIN_MODE. When
set, this indicates to the CFEG that it should only
drain the current queue.

Additionally we no longer want to set the CS_STALL bit
for these multi queue queues as this causes the entire
pipeline to stall waiting for completion of the prior
batch, preventing this soft light restore from occurring
between queues in a queue group.

Bspec: 56551
Signed-off-by: Stuart Summers <stuart.summers@intel.com>
Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
---
 .../gpu/drm/xe/instructions/xe_gpu_commands.h |  1 +
 drivers/gpu/drm/xe/xe_ring_ops.c              | 68 ++++++++++++-------
 2 files changed, 45 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h b/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h
index 5d41ca297447..885fcf211e6d 100644
--- a/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h
+++ b/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h
@@ -47,6 +47,7 @@
 
 #define GFX_OP_PIPE_CONTROL(len)	((0x3<<29)|(0x3<<27)|(0x2<<24)|((len)-2))
 
+#define   PIPE_CONTROL0_QUEUE_DRAIN_MODE		BIT(12)
 #define	  PIPE_CONTROL0_L3_READ_ONLY_CACHE_INVALIDATE	BIT(10)	/* gen12 */
 #define	  PIPE_CONTROL0_HDC_PIPELINE_FLUSH		BIT(9)	/* gen12 */
 
diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c
index ac0c6dcffe15..71f0e19fe8ba 100644
--- a/drivers/gpu/drm/xe/xe_ring_ops.c
+++ b/drivers/gpu/drm/xe/xe_ring_ops.c
@@ -12,7 +12,7 @@
 #include "regs/xe_engine_regs.h"
 #include "regs/xe_gt_regs.h"
 #include "regs/xe_lrc_layout.h"
-#include "xe_exec_queue_types.h"
+#include "xe_exec_queue.h"
 #include "xe_gt.h"
 #include "xe_lrc.h"
 #include "xe_macros.h"
@@ -135,12 +135,11 @@ emit_pipe_control(u32 *dw, int i, u32 bit_group_0, u32 bit_group_1, u32 offset,
 	return i;
 }
 
-static int emit_pipe_invalidate(u32 mask_flags, bool invalidate_tlb, u32 *dw,
-				int i)
+static int emit_pipe_invalidate(struct xe_exec_queue *q, u32 mask_flags,
+				bool invalidate_tlb, u32 *dw, int i)
 {
 	u32 flags0 = 0;
-	u32 flags1 = PIPE_CONTROL_CS_STALL |
-		PIPE_CONTROL_COMMAND_CACHE_INVALIDATE |
+	u32 flags1 = PIPE_CONTROL_COMMAND_CACHE_INVALIDATE |
 		PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE |
 		PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
 		PIPE_CONTROL_VF_CACHE_INVALIDATE |
@@ -152,6 +151,11 @@ static int emit_pipe_invalidate(u32 mask_flags, bool invalidate_tlb, u32 *dw,
 	if (invalidate_tlb)
 		flags1 |= PIPE_CONTROL_TLB_INVALIDATE;
 
+	if (xe_exec_queue_is_multi_queue(q))
+		flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
+	else
+		flags1 |= PIPE_CONTROL_CS_STALL;
+
 	flags1 &= ~mask_flags;
 
 	if (flags1 & PIPE_CONTROL_VF_CACHE_INVALIDATE)
@@ -175,54 +179,70 @@ static int emit_store_imm_ppgtt_posted(u64 addr, u64 value,
 
 static int emit_render_cache_flush(struct xe_sched_job *job, u32 *dw, int i)
 {
-	struct xe_gt *gt = job->q->gt;
+	struct xe_exec_queue *q = job->q;
+	struct xe_gt *gt = q->gt;
 	bool lacks_render = !(gt->info.engine_mask & XE_HW_ENGINE_RCS_MASK);
-	u32 flags;
+	u32 flags0, flags1;
 
 	if (XE_GT_WA(gt, 14016712196))
 		i = emit_pipe_control(dw, i, 0, PIPE_CONTROL_DEPTH_CACHE_FLUSH,
 				      LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR, 0);
 
-	flags = (PIPE_CONTROL_CS_STALL |
-		 PIPE_CONTROL_TILE_CACHE_FLUSH |
+	flags0 = PIPE_CONTROL0_HDC_PIPELINE_FLUSH;
+	flags1 = (PIPE_CONTROL_TILE_CACHE_FLUSH |
 		 PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
 		 PIPE_CONTROL_DEPTH_CACHE_FLUSH |
 		 PIPE_CONTROL_DC_FLUSH_ENABLE |
 		 PIPE_CONTROL_FLUSH_ENABLE);
 
 	if (XE_GT_WA(gt, 1409600907))
-		flags |= PIPE_CONTROL_DEPTH_STALL;
+		flags1 |= PIPE_CONTROL_DEPTH_STALL;
 
 	if (lacks_render)
-		flags &= ~PIPE_CONTROL_3D_ARCH_FLAGS;
+		flags1 &= ~PIPE_CONTROL_3D_ARCH_FLAGS;
 	else if (job->q->class == XE_ENGINE_CLASS_COMPUTE)
-		flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
+		flags1 &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
+
+	if (xe_exec_queue_is_multi_queue(q))
+		flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
+	else
+		flags1 |= PIPE_CONTROL_CS_STALL;
 
-	return emit_pipe_control(dw, i, PIPE_CONTROL0_HDC_PIPELINE_FLUSH, flags, 0, 0);
+	return emit_pipe_control(dw, i, flags0, flags1, 0, 0);
 }
 
-static int emit_pipe_control_to_ring_end(struct xe_hw_engine *hwe, u32 *dw, int i)
+static int emit_pipe_control_to_ring_end(struct xe_exec_queue *q, u32 *dw, int i)
 {
+	u32 flags0 = 0, flags1 = PIPE_CONTROL_LRI_POST_SYNC;
+	struct xe_hw_engine *hwe = q->hwe;
+
 	if (hwe->class != XE_ENGINE_CLASS_RENDER)
 		return i;
 
+	if (xe_exec_queue_is_multi_queue(q))
+		flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
+
 	if (XE_GT_WA(hwe->gt, 16020292621))
-		i = emit_pipe_control(dw, i, 0, PIPE_CONTROL_LRI_POST_SYNC,
+		i = emit_pipe_control(dw, i, flags0, flags1,
 				      RING_NOPID(hwe->mmio_base).addr, 0);
 
 	return i;
 }
 
-static int emit_pipe_imm_ggtt(u32 addr, u32 value, bool stall_only, u32 *dw,
-			      int i)
+static int emit_pipe_imm_ggtt(struct xe_exec_queue *q, u32 addr, u32 value,
+			      bool stall_only, u32 *dw, int i)
 {
-	u32 flags = PIPE_CONTROL_CS_STALL | PIPE_CONTROL_GLOBAL_GTT_IVB |
-		    PIPE_CONTROL_QW_WRITE;
+	u32 flags0 = 0, flags1 = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_QW_WRITE;
 
 	if (!stall_only)
-		flags |= PIPE_CONTROL_FLUSH_ENABLE;
+		flags1 |= PIPE_CONTROL_FLUSH_ENABLE;
+
+	if (xe_exec_queue_is_multi_queue(q))
+		flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
+	else
+		flags1 |= PIPE_CONTROL_CS_STALL;
 
-	return emit_pipe_control(dw, i, 0, flags, addr, value);
+	return emit_pipe_control(dw, i, flags0, flags1, addr, value);
 }
 
 static u32 get_ppgtt_flag(struct xe_sched_job *job)
@@ -371,7 +391,7 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job,
 		mask_flags = PIPE_CONTROL_3D_ENGINE_FLAGS;
 
 	/* See __xe_pt_bind_vma() for a discussion on TLB invalidations. */
-	i = emit_pipe_invalidate(mask_flags, job->ring_ops_flush_tlb, dw, i);
+	i = emit_pipe_invalidate(job->q, mask_flags, job->ring_ops_flush_tlb, dw, i);
 
 	/* hsdes: 1809175790 */
 	if (has_aux_ccs(xe))
@@ -391,11 +411,11 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job,
 						job->user_fence.value,
 						dw, i);
 
-	i = emit_pipe_imm_ggtt(xe_lrc_seqno_ggtt_addr(lrc), seqno, lacks_render, dw, i);
+	i = emit_pipe_imm_ggtt(job->q, xe_lrc_seqno_ggtt_addr(lrc), seqno, lacks_render, dw, i);
 
 	i = emit_user_interrupt(dw, i);
 
-	i = emit_pipe_control_to_ring_end(job->q->hwe, dw, i);
+	i = emit_pipe_control_to_ring_end(job->q, dw, i);
 
 	xe_gt_assert(gt, i <= MAX_JOB_SIZE_DW);
 
-- 
2.43.0


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

* [PATCH v3 11/18] drm/xe/multi_queue: Handle CGP context error
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (9 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 10/18] drm/xe/multi_queue: Set QUEUE_DRAIN_MODE for Multi Queue batches Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-21  3:51 ` [PATCH v3 12/18] drm/xe/multi_queue: Reset GT upon CGP_SYNC failure Niranjana Vishwanathapura
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

Trigger multi-queue context cleanup upon CGP context error
notification from GuC.

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/abi/guc_actions_abi.h |  1 +
 drivers/gpu/drm/xe/xe_guc_ct.c           |  4 +++
 drivers/gpu/drm/xe/xe_guc_submit.c       | 31 ++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_guc_submit.h       |  2 ++
 drivers/gpu/drm/xe/xe_trace.h            |  5 ++++
 5 files changed, 43 insertions(+)

diff --git a/drivers/gpu/drm/xe/abi/guc_actions_abi.h b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
index 3e9fbed9cda6..8af3691626bf 100644
--- a/drivers/gpu/drm/xe/abi/guc_actions_abi.h
+++ b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
@@ -142,6 +142,7 @@ enum xe_guc_action {
 	XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE = 0x4602,
 	XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC = 0x4603,
 	XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE = 0x4604,
+	XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CGP_CONTEXT_ERROR = 0x4605,
 	XE_GUC_ACTION_CLIENT_SOFT_RESET = 0x5507,
 	XE_GUC_ACTION_SET_ENG_UTIL_BUFF = 0x550A,
 	XE_GUC_ACTION_SET_DEVICE_ENGINE_ACTIVITY_BUFFER = 0x550C,
diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c
index 43a79bcdfb18..384a724421cd 100644
--- a/drivers/gpu/drm/xe/xe_guc_ct.c
+++ b/drivers/gpu/drm/xe/xe_guc_ct.c
@@ -1573,6 +1573,10 @@ static int process_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len)
 	case XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE:
 		ret = xe_guc_exec_queue_cgp_sync_done_handler(guc, payload, adj_len);
 		break;
+	case XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CGP_CONTEXT_ERROR:
+		ret = xe_guc_exec_queue_cgp_context_error_handler(guc, payload,
+								  adj_len);
+		break;
 	default:
 		xe_gt_err(gt, "unexpected G2H action 0x%04x\n", action);
 	}
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 2e5fff7ad69b..87a33c06fe26 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -48,6 +48,8 @@
 #include "xe_uc_fw.h"
 #include "xe_vm.h"
 
+#define XE_GUC_EXEC_QUEUE_CGP_CONTEXT_ERROR_LEN		6
+
 static struct xe_guc *
 exec_queue_to_guc(struct xe_exec_queue *q)
 {
@@ -3009,6 +3011,35 @@ int xe_guc_exec_queue_reset_failure_handler(struct xe_guc *guc, u32 *msg, u32 le
 	return 0;
 }
 
+int xe_guc_exec_queue_cgp_context_error_handler(struct xe_guc *guc, u32 *msg,
+						u32 len)
+{
+	struct xe_gt *gt = guc_to_gt(guc);
+	struct xe_device *xe = guc_to_xe(guc);
+	struct xe_exec_queue *q;
+	u32 guc_id = msg[2];
+
+	if (unlikely(len != XE_GUC_EXEC_QUEUE_CGP_CONTEXT_ERROR_LEN)) {
+		drm_err(&xe->drm, "Invalid length %u", len);
+		return -EPROTO;
+	}
+
+	q = g2h_exec_queue_lookup(guc, guc_id);
+	if (unlikely(!q))
+		return -EPROTO;
+
+	xe_gt_dbg(gt,
+		  "CGP context error: region=%s err=0x%x, context=0x%x LRCA=0x%x:0x%x SgId=0x%x",
+		  msg[0] & 1 ? "uc" : "kmd", msg[1], msg[2], msg[4], msg[3], msg[5]);
+
+	trace_xe_exec_queue_cgp_context_error(q);
+
+	/* Treat the same as engine reset */
+	xe_guc_exec_queue_reset_trigger_cleanup(q);
+
+	return 0;
+}
+
 /**
  * xe_guc_exec_queue_cgp_sync_done_handler - CGP synchronization done handler
  * @guc: guc
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.h b/drivers/gpu/drm/xe/xe_guc_submit.h
index abfa94bce391..01b013a90b1b 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.h
+++ b/drivers/gpu/drm/xe/xe_guc_submit.h
@@ -35,6 +35,8 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg,
 int xe_guc_exec_queue_reset_failure_handler(struct xe_guc *guc, u32 *msg, u32 len);
 int xe_guc_error_capture_handler(struct xe_guc *guc, u32 *msg, u32 len);
 int xe_guc_exec_queue_cgp_sync_done_handler(struct xe_guc *guc, u32 *msg, u32 len);
+int xe_guc_exec_queue_cgp_context_error_handler(struct xe_guc *guc, u32 *msg,
+						u32 len);
 
 struct xe_guc_submit_exec_queue_snapshot *
 xe_guc_exec_queue_snapshot_capture(struct xe_exec_queue *q);
diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h
index 79a97b086cb2..c9d0748dae9d 100644
--- a/drivers/gpu/drm/xe/xe_trace.h
+++ b/drivers/gpu/drm/xe/xe_trace.h
@@ -172,6 +172,11 @@ DEFINE_EVENT(xe_exec_queue, xe_exec_queue_memory_cat_error,
 	     TP_ARGS(q)
 );
 
+DEFINE_EVENT(xe_exec_queue, xe_exec_queue_cgp_context_error,
+	     TP_PROTO(struct xe_exec_queue *q),
+	     TP_ARGS(q)
+);
+
 DEFINE_EVENT(xe_exec_queue, xe_exec_queue_stop,
 	     TP_PROTO(struct xe_exec_queue *q),
 	     TP_ARGS(q)
-- 
2.43.0


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

* [PATCH v3 12/18] drm/xe/multi_queue: Reset GT upon CGP_SYNC failure
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (10 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 11/18] drm/xe/multi_queue: Handle CGP context error Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-21 23:08   ` Matthew Brost
  2025-11-21  3:51 ` [PATCH v3 13/18] drm/xe/multi_queue: Tracepoint support Niranjana Vishwanathapura
                   ` (11 subsequent siblings)
  23 siblings, 1 reply; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

If GuC doesn't response to CGP_SYNC message, trigger
GT reset and cleanup of all the queues of the multi
queue group.

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
---
 drivers/gpu/drm/xe/xe_guc_submit.c | 38 ++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 87a33c06fe26..932be1e5001e 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -593,6 +593,23 @@ static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
 		xe_sched_tdr_queue_imm(&q->guc->sched);
 }
 
+static void xe_guc_exec_queue_group_trigger_cleanup(struct xe_exec_queue *q)
+{
+	struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
+	struct xe_exec_queue_group *group = q->multi_queue.group;
+	struct xe_exec_queue *eq;
+
+	xe_gt_assert(guc_to_gt(exec_queue_to_guc(q)),
+		     xe_exec_queue_is_multi_queue(q));
+
+	xe_guc_exec_queue_trigger_cleanup(primary);
+
+	mutex_lock(&group->list_lock);
+	list_for_each_entry(eq, &group->list, multi_queue.link)
+		xe_guc_exec_queue_trigger_cleanup(eq);
+	mutex_unlock(&group->list_lock);
+}
+
 static void xe_guc_exec_queue_reset_trigger_cleanup(struct xe_exec_queue *q)
 {
 	if (xe_exec_queue_is_multi_queue(q)) {
@@ -618,6 +635,23 @@ static void xe_guc_exec_queue_reset_trigger_cleanup(struct xe_exec_queue *q)
 	}
 }
 
+static void set_exec_queue_group_banned(struct xe_exec_queue *q)
+{
+	struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
+	struct xe_exec_queue_group *group = q->multi_queue.group;
+	struct xe_exec_queue *eq;
+
+	/* Ban all queues of the multi-queue group */
+	xe_gt_assert(guc_to_gt(exec_queue_to_guc(q)),
+		     xe_exec_queue_is_multi_queue(q));
+	set_exec_queue_banned(primary);
+
+	mutex_lock(&group->list_lock);
+	list_for_each_entry(eq, &group->list, multi_queue.link)
+		set_exec_queue_banned(eq);
+	mutex_unlock(&group->list_lock);
+}
+
 #define parallel_read(xe_, map_, field_) \
 	xe_map_rd_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
 			field_)
@@ -675,7 +709,11 @@ static void xe_guc_exec_queue_group_cgp_sync(struct xe_guc *guc,
 				 !READ_ONCE(group->sync_pending) ||
 				 xe_guc_read_stopped(guc), HZ);
 	if ((!ret && !vf_recovery(guc)) || xe_guc_read_stopped(guc)) {
+		/* CGP_SYNC failed. Reset gt, cleanup the group */
 		xe_gt_warn(guc_to_gt(guc), "Wait for CGP_SYNC_DONE response failed!\n");
+		set_exec_queue_group_banned(q);
+		xe_gt_reset_async(q->gt);
+		xe_guc_exec_queue_group_trigger_cleanup(q);
 		return;
 	}
 
-- 
2.43.0


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

* [PATCH v3 13/18] drm/xe/multi_queue: Tracepoint support
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (11 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 12/18] drm/xe/multi_queue: Reset GT upon CGP_SYNC failure Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-21  3:51 ` [PATCH v3 14/18] drm/xe/multi_queue: Support active group after primary is destroyed Niranjana Vishwanathapura
                   ` (10 subsequent siblings)
  23 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

Add xe_exec_queue_create_multi_queue event with
multi-queue information.

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_guc_submit.c |  5 +++-
 drivers/gpu/drm/xe/xe_trace.h      | 41 ++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 932be1e5001e..fbe3de30af60 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -2051,7 +2051,10 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
 		mutex_unlock(&group->list_lock);
 	}
 
-	trace_xe_exec_queue_create(q);
+	if (xe_exec_queue_is_multi_queue(q))
+		trace_xe_exec_queue_create_multi_queue(q);
+	else
+		trace_xe_exec_queue_create(q);
 
 	return 0;
 
diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h
index c9d0748dae9d..6d12fcc13f43 100644
--- a/drivers/gpu/drm/xe/xe_trace.h
+++ b/drivers/gpu/drm/xe/xe_trace.h
@@ -13,6 +13,7 @@
 #include <linux/types.h>
 
 #include "xe_exec_queue_types.h"
+#include "xe_exec_queue.h"
 #include "xe_gpu_scheduler_types.h"
 #include "xe_gt_types.h"
 #include "xe_guc_exec_queue_types.h"
@@ -97,11 +98,51 @@ DECLARE_EVENT_CLASS(xe_exec_queue,
 			      __entry->guc_state, __entry->flags)
 );
 
+DECLARE_EVENT_CLASS(xe_exec_queue_multi_queue,
+		    TP_PROTO(struct xe_exec_queue *q),
+		    TP_ARGS(q),
+
+		    TP_STRUCT__entry(
+			     __string(dev, __dev_name_eq(q))
+			     __field(enum xe_engine_class, class)
+			     __field(u32, logical_mask)
+			     __field(u8, gt_id)
+			     __field(u16, width)
+			     __field(u32, guc_id)
+			     __field(u32, guc_state)
+			     __field(u32, flags)
+			     __field(u32, primary)
+			     ),
+
+		    TP_fast_assign(
+			   __assign_str(dev);
+			   __entry->class = q->class;
+			   __entry->logical_mask = q->logical_mask;
+			   __entry->gt_id = q->gt->info.id;
+			   __entry->width = q->width;
+			   __entry->guc_id = q->guc->id;
+			   __entry->guc_state = atomic_read(&q->guc->state);
+			   __entry->flags = q->flags;
+			   __entry->primary = xe_exec_queue_multi_queue_primary(q)->guc->id;
+			   ),
+
+		    TP_printk("dev=%s, %d:0x%x, gt=%d, width=%d guc_id=%d, guc_state=0x%x, flags=0x%x, primary=%d",
+			      __get_str(dev), __entry->class, __entry->logical_mask,
+			      __entry->gt_id, __entry->width, __entry->guc_id,
+			      __entry->guc_state, __entry->flags,
+			      __entry->primary)
+);
+
 DEFINE_EVENT(xe_exec_queue, xe_exec_queue_create,
 	     TP_PROTO(struct xe_exec_queue *q),
 	     TP_ARGS(q)
 );
 
+DEFINE_EVENT(xe_exec_queue_multi_queue, xe_exec_queue_create_multi_queue,
+	     TP_PROTO(struct xe_exec_queue *q),
+	     TP_ARGS(q)
+);
+
 DEFINE_EVENT(xe_exec_queue, xe_exec_queue_supress_resume,
 	     TP_PROTO(struct xe_exec_queue *q),
 	     TP_ARGS(q)
-- 
2.43.0


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

* [PATCH v3 14/18] drm/xe/multi_queue: Support active group after primary is destroyed
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (12 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 13/18] drm/xe/multi_queue: Tracepoint support Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-22  5:57   ` Matthew Brost
  2025-11-21  3:51 ` [PATCH v3 15/18] drm/xe/xe3p: Disable GuC Dynamic ICS for Xe3p Niranjana Vishwanathapura
                   ` (9 subsequent siblings)
  23 siblings, 1 reply; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

Add support to keep the group active after the primary queue is
destroyed. Instead of killing the primary queue during exec_queue
destroy ioctl, kill it when all the secondary queues of the group
are killed.

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
---
 drivers/gpu/drm/xe/xe_device.c           |  7 ++-
 drivers/gpu/drm/xe/xe_exec_queue.c       | 55 +++++++++++++++++++++++-
 drivers/gpu/drm/xe/xe_exec_queue.h       |  2 +
 drivers/gpu/drm/xe/xe_exec_queue_types.h |  4 ++
 include/uapi/drm/xe_drm.h                |  4 ++
 5 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 037206c8b543..e72294a7d4b1 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -177,7 +177,12 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file)
 	xa_for_each(&xef->exec_queue.xa, idx, q) {
 		if (q->vm && q->hwe->hw_engine_group)
 			xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q);
-		xe_exec_queue_kill(q);
+
+		if (xe_exec_queue_is_multi_queue_primary(q))
+			xe_exec_queue_group_kill_put(q->multi_queue.group);
+		else
+			xe_exec_queue_kill(q);
+
 		xe_exec_queue_put(q);
 	}
 	xa_for_each(&xef->vm.xa, idx, vm)
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index ab161b74fef0..839fb08f09e7 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -417,6 +417,26 @@ struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
 }
 ALLOW_ERROR_INJECTION(xe_exec_queue_create_bind, ERRNO);
 
+static void xe_exec_queue_group_kill(struct kref *ref)
+{
+	struct xe_exec_queue_group *group = container_of(ref, struct xe_exec_queue_group,
+							 kill_refcount);
+	xe_exec_queue_kill(group->primary);
+}
+
+static inline void xe_exec_queue_group_kill_get(struct xe_exec_queue_group *group)
+{
+	kref_get(&group->kill_refcount);
+}
+
+void xe_exec_queue_group_kill_put(struct xe_exec_queue_group *group)
+{
+	if (!group)
+		return;
+
+	kref_put(&group->kill_refcount, xe_exec_queue_group_kill);
+}
+
 void xe_exec_queue_destroy(struct kref *ref)
 {
 	struct xe_exec_queue *q = container_of(ref, struct xe_exec_queue, refcount);
@@ -629,6 +649,7 @@ static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue *
 	group->primary = q;
 	group->cgp_bo = bo;
 	INIT_LIST_HEAD(&group->list);
+	kref_init(&group->kill_refcount);
 	xa_init_flags(&group->xa, XA_FLAGS_ALLOC1);
 	mutex_init(&group->list_lock);
 	q->multi_queue.group = group;
@@ -704,6 +725,11 @@ static int xe_exec_queue_group_add(struct xe_device *xe, struct xe_exec_queue *q
 
 	q->multi_queue.pos = pos;
 
+	if (group->primary->multi_queue.keep_active) {
+		xe_exec_queue_group_kill_get(group);
+		q->multi_queue.keep_active = true;
+	}
+
 	return 0;
 }
 
@@ -717,6 +743,11 @@ static void xe_exec_queue_group_delete(struct xe_device *xe, struct xe_exec_queu
 	lrc = xa_erase(&group->xa, q->multi_queue.pos);
 	xe_assert(xe, lrc);
 	xe_lrc_put(lrc);
+
+	if (q->multi_queue.keep_active) {
+		xe_exec_queue_group_kill_put(group);
+		q->multi_queue.keep_active = false;
+	}
 }
 
 static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue *q,
@@ -735,12 +766,24 @@ static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue
 		return -EINVAL;
 
 	if (value & DRM_XE_MULTI_GROUP_CREATE) {
-		if (XE_IOCTL_DBG(xe, value & ~DRM_XE_MULTI_GROUP_CREATE))
+		if (XE_IOCTL_DBG(xe, value & ~(DRM_XE_MULTI_GROUP_CREATE |
+					       DRM_XE_MULTI_GROUP_KEEP_ACTIVE)))
+			return -EINVAL;
+
+		/*
+		 * KEEP_ACTIVE is not supported in preempt fence mode as in that mode,
+		 * VM_DESTROY ioctl expects all exec queues of that VM are already killed.
+		 */
+		if (XE_IOCTL_DBG(xe, (value & DRM_XE_MULTI_GROUP_KEEP_ACTIVE) &&
+				 xe_vm_in_preempt_fence_mode(q->vm)))
 			return -EINVAL;
 
 		q->multi_queue.valid = true;
 		q->multi_queue.is_primary = true;
 		q->multi_queue.pos = 0;
+		if (value & DRM_XE_MULTI_GROUP_KEEP_ACTIVE)
+			q->multi_queue.keep_active = true;
+
 		return 0;
 	}
 
@@ -1286,6 +1329,11 @@ void xe_exec_queue_kill(struct xe_exec_queue *q)
 
 	q->ops->kill(q);
 	xe_vm_remove_compute_exec_queue(q->vm, q);
+
+	if (!xe_exec_queue_is_multi_queue_primary(q) && q->multi_queue.keep_active) {
+		xe_exec_queue_group_kill_put(q->multi_queue.group);
+		q->multi_queue.keep_active = false;
+	}
 }
 
 int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data,
@@ -1312,7 +1360,10 @@ int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data,
 	if (q->vm && q->hwe->hw_engine_group)
 		xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q);
 
-	xe_exec_queue_kill(q);
+	if (xe_exec_queue_is_multi_queue_primary(q))
+		xe_exec_queue_group_kill_put(q->multi_queue.group);
+	else
+		xe_exec_queue_kill(q);
 
 	trace_xe_exec_queue_close(q);
 	xe_exec_queue_put(q);
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.h b/drivers/gpu/drm/xe/xe_exec_queue.h
index ffcc1feb879e..10abed98fb6b 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue.h
@@ -113,6 +113,8 @@ static inline struct xe_exec_queue *xe_exec_queue_multi_queue_primary(struct xe_
 	return xe_exec_queue_is_multi_queue(q) ? q->multi_queue.group->primary : q;
 }
 
+void xe_exec_queue_group_kill_put(struct xe_exec_queue_group *group);
+
 bool xe_exec_queue_is_lr(struct xe_exec_queue *q);
 
 bool xe_exec_queue_is_idle(struct xe_exec_queue *q);
diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
index 5721fb4bad1a..c6b80977ff4f 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
@@ -62,6 +62,8 @@ struct xe_exec_queue_group {
 	struct list_head list;
 	/** @list_lock: Secondary queue list lock */
 	struct mutex list_lock;
+	/** @kill_refcount: ref count to kill primary queue */
+	struct kref kill_refcount;
 	/** @sync_pending: CGP_SYNC_DONE g2h response pending */
 	bool sync_pending;
 };
@@ -159,6 +161,8 @@ struct xe_exec_queue {
 		u8 valid:1;
 		/** @multi_queue.is_primary: Is primary queue (Q0) of the group */
 		u8 is_primary:1;
+		/** @multi_queue.keep_active: Keep the group active after primary is destroyed */
+		u8 keep_active:1;
 	} multi_queue;
 
 	/** @sched_props: scheduling properties */
diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
index 71a851615876..74cbebb24aa5 100644
--- a/include/uapi/drm/xe_drm.h
+++ b/include/uapi/drm/xe_drm.h
@@ -1260,6 +1260,9 @@ struct drm_xe_vm_bind {
  *    then a new multi-queue group is created with this queue as the primary queue
  *    (Q0). Otherwise, the queue gets added to the multi-queue group whose primary
  *    queue's exec_queue_id is specified in the lower 32 bits of the 'value' field.
+ *    If the extension's 'value' field has %DRM_XE_MULTI_GROUP_KEEP_ACTIVE flag
+ *    set, then the multi-queue group is kept active after the primary queue is
+ *    destroyed.
  *    All the other non-relevant bits of extension's 'value' field while adding the
  *    primary or the secondary queues of the group must be set to 0.
  *  - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY - Set the queue
@@ -1307,6 +1310,7 @@ struct drm_xe_exec_queue_create {
 #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE		2
 #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP		3
 #define     DRM_XE_MULTI_GROUP_CREATE				(1ull << 63)
+#define     DRM_XE_MULTI_GROUP_KEEP_ACTIVE			(1ull << 62)
 #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY	4
 	/** @extensions: Pointer to the first extension struct, if any */
 	__u64 extensions;
-- 
2.43.0


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

* [PATCH v3 15/18] drm/xe/xe3p: Disable GuC Dynamic ICS for Xe3p
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (13 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 14/18] drm/xe/multi_queue: Support active group after primary is destroyed Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-21  3:51 ` [PATCH v3 16/18] drm/xe/doc: Add documentation for Multi Queue Group Niranjana Vishwanathapura
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

From: Gustavo Sousa <gustavo.sousa@intel.com>

The Dynamic Inhibit Context Switch (ICS) feature is not currently
supported on Xe3p with multi-queue feature as it conflicts with
that on the GuC side. Disable ICS to support multi-queue on Xe3p
platforms.

Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
---
 drivers/gpu/drm/xe/xe_guc.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c
index cf92de1c88a7..d092881607ba 100644
--- a/drivers/gpu/drm/xe/xe_guc.c
+++ b/drivers/gpu/drm/xe/xe_guc.c
@@ -607,6 +607,13 @@ static bool supports_dynamic_ics(struct xe_guc *guc)
 	if (xe_gt_is_media_type(gt) || gt->ccs_mode > 1)
 		return false;
 
+	/*
+	 * The feature is currently not compatible with platforms with support
+	 * to multi-queue, even if the feature is not enabled/used.
+	 */
+	if (GRAPHICS_VER(xe) >= 35)
+		return false;
+
 	/*
 	 * Dynamic ICS requires GuC v70.40.1, which maps to compatibility
 	 * version v1.18.4.
-- 
2.43.0


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

* [PATCH v3 16/18] drm/xe/doc: Add documentation for Multi Queue Group
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (14 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 15/18] drm/xe/xe3p: Disable GuC Dynamic ICS for Xe3p Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-22  6:02   ` Matthew Brost
  2025-11-21  3:51 ` [PATCH v3 17/18] drm/xe/doc: Add documentation for Multi Queue Group GuC interface Niranjana Vishwanathapura
                   ` (7 subsequent siblings)
  23 siblings, 1 reply; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

Add kernel documentation for Multi Queue group and update
the corresponding rst.

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
---
 Documentation/gpu/xe/xe_exec_queue.rst |  6 ++++
 drivers/gpu/drm/xe/xe_exec_queue.c     | 45 ++++++++++++++++++++++++++
 2 files changed, 51 insertions(+)

diff --git a/Documentation/gpu/xe/xe_exec_queue.rst b/Documentation/gpu/xe/xe_exec_queue.rst
index 6076569e311c..732af4741df4 100644
--- a/Documentation/gpu/xe/xe_exec_queue.rst
+++ b/Documentation/gpu/xe/xe_exec_queue.rst
@@ -7,6 +7,12 @@ Execution Queue
 .. kernel-doc:: drivers/gpu/drm/xe/xe_exec_queue.c
    :doc: Execution Queue
 
+Multi Queue Group
+=================
+
+.. kernel-doc:: drivers/gpu/drm/xe/xe_exec_queue.c
+   :doc: Multi Queue Group
+
 Internal API
 ============
 
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index 839fb08f09e7..50326b4431e0 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -54,6 +54,51 @@
  * the ring operations the different engine classes support.
  */
 
+/**
+ * DOC: Multi Queue Group
+ *
+ * Multi Queue Group is another mode of execution supported by the compute
+ * and blitter copy command streamers (CCS and BCS, respectively). It is
+ * an enhancement of the existing hardware architecture and leverages the
+ * same submission model. It enables support for efficient, parallel
+ * execution of multiple queues within a single shared context. The multi
+ * queue group functionality is only supported with GuC submission backend.
+ * All the queues of a group must use the same address space (VM).
+ *
+ * The DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE execution queue property
+ * supports creating a multi queue group and adding queues to a queue group.
+ *
+ * The XE_EXEC_QUEUE_CREATE ioctl call with above property with value field
+ * set to DRM_XE_MULTI_GROUP_CREATE, will create a new multi queue group with
+ * the queue being created as the primary queue (aka q0) of the group. To add
+ * secondary queues to the group, they need to be created with the above
+ * property with id of the primary queue as the value. The properties of
+ * the primary queue (like priority, time slice) applies to the whole group.
+ * So, these properties can't be set for secondary queues of a group.
+ *
+ * The hardware does not support removing a queue from a multi-queue group.
+ * However, queues can be dynamically added to the group. A group can have
+ * up to 64 queues. To support this, XeKMD holds references to LRCs of the
+ * queues even after the queues are destroyed by the user until the whole
+ * group is destroyed. The secondary queues hold a reference to the primary
+ * queue thus preventing the group from being destroyed when user destroys
+ * the primary queue. Once the primary queue is destroyed, secondary queues
+ * can't be added to the queue group, but they can continue to submit the
+ * jobs if the DRM_XE_MULTI_GROUP_KEEP_ACTIVE flag is set during the multi
+ * queue group creation.
+ *
+ * The queues of a multi queue group can set their priority within the group
+ * through the DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY property.
+ * This multi queue priority can also be set dynamically through the
+ * XE_EXEC_QUEUE_SET_PROPERTY ioctl. This is the only other property
+ * supported by the secondary queues of a multi queue group, other than
+ * DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE.
+ *
+ * When GuC reports an error on any of the queues of a multi queue group,
+ * the queue cleanup mechanism is invoked for all the queues of the group
+ * as hardware cannot make progress on the multi queue context.
+ */
+
 enum xe_exec_queue_sched_prop {
 	XE_EXEC_QUEUE_JOB_TIMEOUT = 0,
 	XE_EXEC_QUEUE_TIMESLICE = 1,
-- 
2.43.0


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

* [PATCH v3 17/18] drm/xe/doc: Add documentation for Multi Queue Group GuC interface
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (15 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 16/18] drm/xe/doc: Add documentation for Multi Queue Group Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-22  6:10   ` Matthew Brost
  2025-11-21  3:51 ` [PATCH v3 18/18] drm/xe/multi_queue: Enable multi_queue on xe3p_xpc Niranjana Vishwanathapura
                   ` (6 subsequent siblings)
  23 siblings, 1 reply; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

Add kernel documentation for Multi Queue group GuC interface.

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
---
 Documentation/gpu/xe/xe_exec_queue.rst |  8 ++++
 drivers/gpu/drm/xe/xe_exec_queue.c     |  3 ++
 drivers/gpu/drm/xe/xe_guc_submit.c     | 57 ++++++++++++++++++++++++++
 3 files changed, 68 insertions(+)

diff --git a/Documentation/gpu/xe/xe_exec_queue.rst b/Documentation/gpu/xe/xe_exec_queue.rst
index 732af4741df4..8707806211c9 100644
--- a/Documentation/gpu/xe/xe_exec_queue.rst
+++ b/Documentation/gpu/xe/xe_exec_queue.rst
@@ -13,6 +13,14 @@ Multi Queue Group
 .. kernel-doc:: drivers/gpu/drm/xe/xe_exec_queue.c
    :doc: Multi Queue Group
 
+.. _multi-queue-group-guc-interface:
+
+Multi Queue Group GuC interface
+===============================
+
+.. kernel-doc:: drivers/gpu/drm/xe/xe_guc_submit.c
+   :doc: Multi Queue Group GuC interface
+
 Internal API
 ============
 
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index 50326b4431e0..387497dfd5b1 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -97,6 +97,9 @@
  * When GuC reports an error on any of the queues of a multi queue group,
  * the queue cleanup mechanism is invoked for all the queues of the group
  * as hardware cannot make progress on the multi queue context.
+ *
+ * Refer :ref:`multi-queue-group-guc-interface` for multi queue group GuC
+ * interface.
  */
 
 enum xe_exec_queue_sched_prop {
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index fbe3de30af60..86946760ad0f 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -659,6 +659,63 @@ static void set_exec_queue_group_banned(struct xe_exec_queue *q)
 	xe_map_wr_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
 			field_, val_)
 
+/**
+ * DOC: Multi Queue Group GuC interface
+ *
+ * The multi queue group coordination between KMD and GuC is through a software
+ * construct called Context Group Page (CGP). The CGP is a KMD managed 4KB page
+ * allocated in the global GTT.
+ *
+ * CGP format:
+ *
+ * +-----------+---------------------------+---------------------------------------------+
+ * | DWORD     | Name                      | Description                                 |
+ * +-----------+---------------------------+---------------------------------------------+
+ * | 0         | Version                   | Bits [15:8]=Major ver, [7:0]=Minor ver      |
+ * +-----------+---------------------------+---------------------------------------------+
+ * | 1..15     | RESERVED                  | MBZ                                         |
+ * +-----------+---------------------------+---------------------------------------------+
+ * | 16        | KMD_QUEUE_UPDATE_MASK_DW0 | KMD queue mask for queues 31..0             |
+ * +-----------+---------------------------+---------------------------------------------+
+ * | 17        | KMD_QUEUE_UPDATE_MASK_DW1 | KMD queue mask for queues 63..32            |
+ * +-----------+---------------------------+---------------------------------------------+
+ * | 18..31    | RESERVED                  | MBZ                                         |
+ * +-----------+---------------------------+---------------------------------------------+
+ * | 32        | Q0CD_DW0                  | Queue 0 context LRC descriptor lower DWORD  |
+ * +-----------+---------------------------+---------------------------------------------+
+ * | 33        | Q0ContextIndex            | Context ID for Queue 0                      |
+ * +-----------+---------------------------+---------------------------------------------+
+ * | 34        | Q1CD_DW0                  | Queue 1 context LRC descriptor lower DWORD  |
+ * +-----------+---------------------------+---------------------------------------------+
+ * | 35        | Q1ContextIndex            | Context ID for Queue 1                      |
+ * +-----------+---------------------------+---------------------------------------------+
+ * | ...       |...                        | ...                                         |
+ * +-----------+---------------------------+---------------------------------------------+
+ * | 158       | Q63CD_DW0                 | Queue 63 context LRC descriptor lower DWORD |
+ * +-----------+---------------------------+---------------------------------------------+
+ * | 159       | Q63ContextIndex           | Context ID for Queue 63                     |
+ * +-----------+---------------------------+---------------------------------------------+
+ * | 160..1024 | RESERVED                  | MBZ                                         |
+ * +-----------+---------------------------+---------------------------------------------+
+ *
+ * While registering Q0 with GuC, CGP is updated with Q0 entry and GuC is notified
+ * through XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE H2G message which specifies
+ * the CGP address. When the secondary queues are added to the group, the CGP is
+ * updated with entry for that queue and GuC is notified through the H2G interface
+ * XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC. GuC responds to these H2G messages
+ * with a XE_GUC_ACTION_NOTIFY_MULTIQ_CONTEXT_CGP_SYNC_DONE G2H message. GuC also
+ * sends a XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CGP_CONTEXT_ERROR notification for any
+ * error in the CGP. Only one of these CGP update messages can be outstanding
+ * (waiting for GuC response) at any time. The bits in KMD_QUEUE_UPDATE_MASK_DW*
+ * fields indicate which queue entry is being updated in the CGP.
+ *
+ * The primary queue (Q0) represents the multi queue group context in GuC and
+ * submission on any queue of the group must be through Q0 GuC interface only.
+ *
+ * As it is not required to register secondary queues with GuC, the secondary queue
+ * context ids in the CGP are populated with Q0 context id.
+ */
+
 #define CGP_VERSION_MAJOR_SHIFT	8
 
 static void xe_guc_exec_queue_group_cgp_update(struct xe_device *xe,
-- 
2.43.0


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

* [PATCH v3 18/18] drm/xe/multi_queue: Enable multi_queue on xe3p_xpc
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (16 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 17/18] drm/xe/doc: Add documentation for Multi Queue Group GuC interface Niranjana Vishwanathapura
@ 2025-11-21  3:51 ` Niranjana Vishwanathapura
  2025-11-21  4:01 ` ✗ CI.checkpatch: warning for drm/xe: Multi Queue feature support (rev3) Patchwork
                   ` (5 subsequent siblings)
  23 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-21  3:51 UTC (permalink / raw)
  To: intel-xe; +Cc: matthew.brost

xe3p_xpc supports multi_queue, enable it.

v2: Rename multi_queue_enable_mask to multi_queue_engine_class_mask
    (Matt Brost)

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_pci.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index f9464398e3ea..5c703b0db6f3 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -111,6 +111,8 @@ static const struct xe_graphics_desc graphics_xe3p_xpc = {
 	.hw_engine_mask =
 		GENMASK(XE_HW_ENGINE_BCS8, XE_HW_ENGINE_BCS1) |
 		GENMASK(XE_HW_ENGINE_CCS3, XE_HW_ENGINE_CCS0),
+	.multi_queue_engine_class_mask = BIT(XE_ENGINE_CLASS_COPY) |
+					 BIT(XE_ENGINE_CLASS_COMPUTE),
 };
 
 static const struct xe_media_desc media_xem = {
-- 
2.43.0


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

* ✗ CI.checkpatch: warning for drm/xe: Multi Queue feature support (rev3)
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (17 preceding siblings ...)
  2025-11-21  3:51 ` [PATCH v3 18/18] drm/xe/multi_queue: Enable multi_queue on xe3p_xpc Niranjana Vishwanathapura
@ 2025-11-21  4:01 ` Patchwork
  2025-11-21  4:02 ` ✓ CI.KUnit: success " Patchwork
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 41+ messages in thread
From: Patchwork @ 2025-11-21  4:01 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

== Series Details ==

Series: drm/xe: Multi Queue feature support (rev3)
URL   : https://patchwork.freedesktop.org/series/156865/
State : warning

== Summary ==

+ KERNEL=/kernel
+ git clone https://gitlab.freedesktop.org/drm/maintainer-tools mt
Cloning into 'mt'...
warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
+ git -C mt rev-list -n1 origin/master
2de9a3901bc28757c7906b454717b64e2a214021
+ cd /kernel
+ git config --global --add safe.directory /kernel
+ git log -n1
commit 1281c9f7fe58cd9bd4ec167922e4a28f8843991c
Author: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Date:   Thu Nov 20 19:51:52 2025 -0800

    drm/xe/multi_queue: Enable multi_queue on xe3p_xpc
    
    xe3p_xpc supports multi_queue, enable it.
    
    v2: Rename multi_queue_enable_mask to multi_queue_engine_class_mask
        (Matt Brost)
    
    Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
    Reviewed-by: Matthew Brost <matthew.brost@intel.com>
+ /mt/dim checkpatch 3d718db04a365cc44a3bc81ffa4db7bbd2e645d7 drm-intel
0df37791a4c3 drm/xe/multi_queue: Add multi_queue_enable_mask to gt information
4ba810b2f506 drm/xe/multi_queue: Add user interface for multi queue support
cf8264933995 drm/xe/multi_queue: Add GuC interface for multi queue support
44bbd9a48c98 drm/xe/multi_queue: Add multi queue priority property
30d771d318cc drm/xe/multi_queue: Handle invalid exec queue property setting
1486f2bf7345 drm/xe/multi_queue: Add exec_queue set_property ioctl support
-:109: WARNING:LONG_LINE: line length of 145 exceeds 100 columns
#109: FILE: include/uapi/drm/xe_drm.h:127:
+#define DRM_IOCTL_XE_EXEC_QUEUE_SET_PROPERTY	DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC_QUEUE_SET_PROPERTY, struct drm_xe_exec_queue_set_property)

total: 0 errors, 1 warnings, 0 checks, 101 lines checked
3ebdd1fa8f2f drm/xe/multi_queue: Add support for multi queue dynamic priority change
14eac2a1fb37 drm/xe/multi_queue: Add multi queue information to guc_info dump
16eacd13fea1 drm/xe/multi_queue: Handle tearing down of a multi queue
426c2f93a5ef drm/xe/multi_queue: Set QUEUE_DRAIN_MODE for Multi Queue batches
63a77c5edba4 drm/xe/multi_queue: Handle CGP context error
1068c65f407b drm/xe/multi_queue: Reset GT upon CGP_SYNC failure
d3ba88601115 drm/xe/multi_queue: Tracepoint support
-:48: CHECK:OPEN_ENDED_LINE: Lines should not end with a '('
#48: FILE: drivers/gpu/drm/xe/xe_trace.h:105:
+		    TP_STRUCT__entry(

-:60: CHECK:OPEN_ENDED_LINE: Lines should not end with a '('
#60: FILE: drivers/gpu/drm/xe/xe_trace.h:117:
+		    TP_fast_assign(

total: 0 errors, 0 warnings, 2 checks, 69 lines checked
2086eceebd36 drm/xe/multi_queue: Support active group after primary is destroyed
5c67e0b327d8 drm/xe/xe3p: Disable GuC Dynamic ICS for Xe3p
6232edcd2bd6 drm/xe/doc: Add documentation for Multi Queue Group
ddc795983dbf drm/xe/doc: Add documentation for Multi Queue Group GuC interface
1281c9f7fe58 drm/xe/multi_queue: Enable multi_queue on xe3p_xpc



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

* ✓ CI.KUnit: success for drm/xe: Multi Queue feature support (rev3)
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (18 preceding siblings ...)
  2025-11-21  4:01 ` ✗ CI.checkpatch: warning for drm/xe: Multi Queue feature support (rev3) Patchwork
@ 2025-11-21  4:02 ` Patchwork
  2025-11-21  4:51 ` ✗ Xe.CI.BAT: failure " Patchwork
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 41+ messages in thread
From: Patchwork @ 2025-11-21  4:02 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

== Series Details ==

Series: drm/xe: Multi Queue feature support (rev3)
URL   : https://patchwork.freedesktop.org/series/156865/
State : success

== Summary ==

+ trap cleanup EXIT
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig
[04:01:14] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[04:01:18] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[04:01:49] Starting KUnit Kernel (1/1)...
[04:01:49] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[04:01:49] ================== guc_buf (11 subtests) ===================
[04:01:49] [PASSED] test_smallest
[04:01:49] [PASSED] test_largest
[04:01:49] [PASSED] test_granular
[04:01:49] [PASSED] test_unique
[04:01:49] [PASSED] test_overlap
[04:01:49] [PASSED] test_reusable
[04:01:49] [PASSED] test_too_big
[04:01:49] [PASSED] test_flush
[04:01:49] [PASSED] test_lookup
[04:01:49] [PASSED] test_data
[04:01:49] [PASSED] test_class
[04:01:49] ===================== [PASSED] guc_buf =====================
[04:01:49] =================== guc_dbm (7 subtests) ===================
[04:01:49] [PASSED] test_empty
[04:01:49] [PASSED] test_default
[04:01:49] ======================== test_size  ========================
[04:01:49] [PASSED] 4
[04:01:49] [PASSED] 8
[04:01:49] [PASSED] 32
[04:01:49] [PASSED] 256
[04:01:49] ==================== [PASSED] test_size ====================
[04:01:49] ======================= test_reuse  ========================
[04:01:49] [PASSED] 4
[04:01:49] [PASSED] 8
[04:01:49] [PASSED] 32
[04:01:49] [PASSED] 256
[04:01:49] =================== [PASSED] test_reuse ====================
[04:01:49] =================== test_range_overlap  ====================
[04:01:49] [PASSED] 4
[04:01:49] [PASSED] 8
[04:01:49] [PASSED] 32
[04:01:49] [PASSED] 256
[04:01:49] =============== [PASSED] test_range_overlap ================
[04:01:49] =================== test_range_compact  ====================
[04:01:49] [PASSED] 4
[04:01:49] [PASSED] 8
[04:01:49] [PASSED] 32
[04:01:49] [PASSED] 256
[04:01:49] =============== [PASSED] test_range_compact ================
[04:01:49] ==================== test_range_spare  =====================
[04:01:49] [PASSED] 4
[04:01:49] [PASSED] 8
[04:01:49] [PASSED] 32
[04:01:49] [PASSED] 256
[04:01:49] ================ [PASSED] test_range_spare =================
[04:01:49] ===================== [PASSED] guc_dbm =====================
[04:01:49] =================== guc_idm (6 subtests) ===================
[04:01:49] [PASSED] bad_init
[04:01:49] [PASSED] no_init
[04:01:49] [PASSED] init_fini
[04:01:49] [PASSED] check_used
[04:01:49] [PASSED] check_quota
[04:01:49] [PASSED] check_all
[04:01:49] ===================== [PASSED] guc_idm =====================
[04:01:49] ================== no_relay (3 subtests) ===================
[04:01:49] [PASSED] xe_drops_guc2pf_if_not_ready
[04:01:49] [PASSED] xe_drops_guc2vf_if_not_ready
[04:01:49] [PASSED] xe_rejects_send_if_not_ready
[04:01:49] ==================== [PASSED] no_relay =====================
[04:01:49] ================== pf_relay (14 subtests) ==================
[04:01:49] [PASSED] pf_rejects_guc2pf_too_short
[04:01:49] [PASSED] pf_rejects_guc2pf_too_long
[04:01:49] [PASSED] pf_rejects_guc2pf_no_payload
[04:01:49] [PASSED] pf_fails_no_payload
[04:01:49] [PASSED] pf_fails_bad_origin
[04:01:49] [PASSED] pf_fails_bad_type
[04:01:49] [PASSED] pf_txn_reports_error
[04:01:49] [PASSED] pf_txn_sends_pf2guc
[04:01:49] [PASSED] pf_sends_pf2guc
[04:01:49] [SKIPPED] pf_loopback_nop
[04:01:49] [SKIPPED] pf_loopback_echo
[04:01:49] [SKIPPED] pf_loopback_fail
[04:01:49] [SKIPPED] pf_loopback_busy
[04:01:49] [SKIPPED] pf_loopback_retry
[04:01:49] ==================== [PASSED] pf_relay =====================
[04:01:49] ================== vf_relay (3 subtests) ===================
[04:01:49] [PASSED] vf_rejects_guc2vf_too_short
[04:01:49] [PASSED] vf_rejects_guc2vf_too_long
[04:01:49] [PASSED] vf_rejects_guc2vf_no_payload
[04:01:49] ==================== [PASSED] vf_relay =====================
[04:01:49] ================ pf_gt_config (6 subtests) =================
[04:01:49] [PASSED] fair_contexts_1vf
[04:01:49] [PASSED] fair_doorbells_1vf
[04:01:49] [PASSED] fair_ggtt_1vf
[04:01:49] ====================== fair_contexts  ======================
[04:01:49] [PASSED] 1 VF
[04:01:49] [PASSED] 2 VFs
[04:01:49] [PASSED] 3 VFs
[04:01:49] [PASSED] 4 VFs
[04:01:49] [PASSED] 5 VFs
[04:01:49] [PASSED] 6 VFs
[04:01:49] [PASSED] 7 VFs
[04:01:49] [PASSED] 8 VFs
[04:01:49] [PASSED] 9 VFs
[04:01:49] [PASSED] 10 VFs
[04:01:49] [PASSED] 11 VFs
[04:01:49] [PASSED] 12 VFs
[04:01:49] [PASSED] 13 VFs
[04:01:49] [PASSED] 14 VFs
[04:01:49] [PASSED] 15 VFs
[04:01:49] [PASSED] 16 VFs
[04:01:49] [PASSED] 17 VFs
[04:01:49] [PASSED] 18 VFs
[04:01:49] [PASSED] 19 VFs
[04:01:49] [PASSED] 20 VFs
[04:01:49] [PASSED] 21 VFs
[04:01:49] [PASSED] 22 VFs
[04:01:49] [PASSED] 23 VFs
[04:01:49] [PASSED] 24 VFs
[04:01:49] [PASSED] 25 VFs
[04:01:49] [PASSED] 26 VFs
[04:01:49] [PASSED] 27 VFs
[04:01:49] [PASSED] 28 VFs
[04:01:49] [PASSED] 29 VFs
[04:01:49] [PASSED] 30 VFs
[04:01:49] [PASSED] 31 VFs
[04:01:49] [PASSED] 32 VFs
[04:01:49] [PASSED] 33 VFs
[04:01:49] [PASSED] 34 VFs
[04:01:49] [PASSED] 35 VFs
[04:01:49] [PASSED] 36 VFs
[04:01:49] [PASSED] 37 VFs
[04:01:49] [PASSED] 38 VFs
[04:01:49] [PASSED] 39 VFs
[04:01:49] [PASSED] 40 VFs
[04:01:49] [PASSED] 41 VFs
[04:01:49] [PASSED] 42 VFs
[04:01:49] [PASSED] 43 VFs
[04:01:49] [PASSED] 44 VFs
[04:01:49] [PASSED] 45 VFs
[04:01:49] [PASSED] 46 VFs
[04:01:49] [PASSED] 47 VFs
[04:01:49] [PASSED] 48 VFs
[04:01:49] [PASSED] 49 VFs
[04:01:49] [PASSED] 50 VFs
[04:01:49] [PASSED] 51 VFs
[04:01:49] [PASSED] 52 VFs
[04:01:49] [PASSED] 53 VFs
[04:01:49] [PASSED] 54 VFs
[04:01:49] [PASSED] 55 VFs
[04:01:49] [PASSED] 56 VFs
[04:01:49] [PASSED] 57 VFs
[04:01:49] [PASSED] 58 VFs
[04:01:49] [PASSED] 59 VFs
[04:01:49] [PASSED] 60 VFs
[04:01:49] [PASSED] 61 VFs
[04:01:49] [PASSED] 62 VFs
[04:01:49] [PASSED] 63 VFs
[04:01:49] ================== [PASSED] fair_contexts ==================
[04:01:49] ===================== fair_doorbells  ======================
[04:01:49] [PASSED] 1 VF
[04:01:49] [PASSED] 2 VFs
[04:01:49] [PASSED] 3 VFs
[04:01:49] [PASSED] 4 VFs
[04:01:49] [PASSED] 5 VFs
[04:01:49] [PASSED] 6 VFs
[04:01:49] [PASSED] 7 VFs
[04:01:49] [PASSED] 8 VFs
[04:01:49] [PASSED] 9 VFs
[04:01:49] [PASSED] 10 VFs
[04:01:49] [PASSED] 11 VFs
[04:01:49] [PASSED] 12 VFs
[04:01:49] [PASSED] 13 VFs
[04:01:49] [PASSED] 14 VFs
[04:01:49] [PASSED] 15 VFs
[04:01:49] [PASSED] 16 VFs
[04:01:49] [PASSED] 17 VFs
[04:01:49] [PASSED] 18 VFs
[04:01:49] [PASSED] 19 VFs
[04:01:49] [PASSED] 20 VFs
[04:01:49] [PASSED] 21 VFs
[04:01:49] [PASSED] 22 VFs
[04:01:49] [PASSED] 23 VFs
[04:01:49] [PASSED] 24 VFs
[04:01:49] [PASSED] 25 VFs
[04:01:49] [PASSED] 26 VFs
[04:01:49] [PASSED] 27 VFs
[04:01:49] [PASSED] 28 VFs
[04:01:49] [PASSED] 29 VFs
[04:01:49] [PASSED] 30 VFs
[04:01:49] [PASSED] 31 VFs
[04:01:49] [PASSED] 32 VFs
[04:01:49] [PASSED] 33 VFs
[04:01:49] [PASSED] 34 VFs
[04:01:49] [PASSED] 35 VFs
[04:01:49] [PASSED] 36 VFs
[04:01:49] [PASSED] 37 VFs
[04:01:49] [PASSED] 38 VFs
[04:01:49] [PASSED] 39 VFs
[04:01:49] [PASSED] 40 VFs
[04:01:49] [PASSED] 41 VFs
[04:01:49] [PASSED] 42 VFs
[04:01:49] [PASSED] 43 VFs
[04:01:49] [PASSED] 44 VFs
[04:01:49] [PASSED] 45 VFs
[04:01:49] [PASSED] 46 VFs
[04:01:49] [PASSED] 47 VFs
[04:01:49] [PASSED] 48 VFs
[04:01:49] [PASSED] 49 VFs
[04:01:49] [PASSED] 50 VFs
[04:01:49] [PASSED] 51 VFs
[04:01:49] [PASSED] 52 VFs
[04:01:49] [PASSED] 53 VFs
[04:01:49] [PASSED] 54 VFs
[04:01:49] [PASSED] 55 VFs
[04:01:49] [PASSED] 56 VFs
[04:01:49] [PASSED] 57 VFs
[04:01:49] [PASSED] 58 VFs
[04:01:49] [PASSED] 59 VFs
[04:01:49] [PASSED] 60 VFs
[04:01:49] [PASSED] 61 VFs
[04:01:49] [PASSED] 62 VFs
[04:01:49] [PASSED] 63 VFs
[04:01:49] ================= [PASSED] fair_doorbells ==================
[04:01:49] ======================== fair_ggtt  ========================
[04:01:49] [PASSED] 1 VF
[04:01:49] [PASSED] 2 VFs
[04:01:49] [PASSED] 3 VFs
[04:01:49] [PASSED] 4 VFs
[04:01:49] [PASSED] 5 VFs
[04:01:49] [PASSED] 6 VFs
[04:01:49] [PASSED] 7 VFs
[04:01:49] [PASSED] 8 VFs
[04:01:49] [PASSED] 9 VFs
[04:01:49] [PASSED] 10 VFs
[04:01:49] [PASSED] 11 VFs
[04:01:49] [PASSED] 12 VFs
[04:01:49] [PASSED] 13 VFs
[04:01:49] [PASSED] 14 VFs
[04:01:49] [PASSED] 15 VFs
[04:01:49] [PASSED] 16 VFs
[04:01:49] [PASSED] 17 VFs
[04:01:49] [PASSED] 18 VFs
[04:01:49] [PASSED] 19 VFs
[04:01:49] [PASSED] 20 VFs
[04:01:49] [PASSED] 21 VFs
[04:01:49] [PASSED] 22 VFs
[04:01:49] [PASSED] 23 VFs
[04:01:49] [PASSED] 24 VFs
[04:01:49] [PASSED] 25 VFs
[04:01:49] [PASSED] 26 VFs
[04:01:49] [PASSED] 27 VFs
[04:01:49] [PASSED] 28 VFs
[04:01:49] [PASSED] 29 VFs
[04:01:49] [PASSED] 30 VFs
[04:01:49] [PASSED] 31 VFs
[04:01:49] [PASSED] 32 VFs
[04:01:49] [PASSED] 33 VFs
[04:01:49] [PASSED] 34 VFs
[04:01:49] [PASSED] 35 VFs
[04:01:49] [PASSED] 36 VFs
[04:01:49] [PASSED] 37 VFs
[04:01:49] [PASSED] 38 VFs
[04:01:49] [PASSED] 39 VFs
[04:01:49] [PASSED] 40 VFs
[04:01:49] [PASSED] 41 VFs
[04:01:49] [PASSED] 42 VFs
[04:01:49] [PASSED] 43 VFs
[04:01:49] [PASSED] 44 VFs
[04:01:49] [PASSED] 45 VFs
[04:01:49] [PASSED] 46 VFs
[04:01:49] [PASSED] 47 VFs
[04:01:49] [PASSED] 48 VFs
[04:01:49] [PASSED] 49 VFs
[04:01:49] [PASSED] 50 VFs
[04:01:49] [PASSED] 51 VFs
[04:01:49] [PASSED] 52 VFs
[04:01:49] [PASSED] 53 VFs
[04:01:49] [PASSED] 54 VFs
[04:01:49] [PASSED] 55 VFs
[04:01:49] [PASSED] 56 VFs
[04:01:49] [PASSED] 57 VFs
[04:01:49] [PASSED] 58 VFs
[04:01:49] [PASSED] 59 VFs
[04:01:49] [PASSED] 60 VFs
[04:01:49] [PASSED] 61 VFs
[04:01:49] [PASSED] 62 VFs
[04:01:49] [PASSED] 63 VFs
[04:01:49] ==================== [PASSED] fair_ggtt ====================
[04:01:49] ================== [PASSED] pf_gt_config ===================
[04:01:49] ===================== lmtt (1 subtest) =====================
[04:01:49] ======================== test_ops  =========================
[04:01:49] [PASSED] 2-level
[04:01:49] [PASSED] multi-level
[04:01:49] ==================== [PASSED] test_ops =====================
[04:01:49] ====================== [PASSED] lmtt =======================
[04:01:49] ================= pf_service (11 subtests) =================
[04:01:49] [PASSED] pf_negotiate_any
[04:01:49] [PASSED] pf_negotiate_base_match
[04:01:49] [PASSED] pf_negotiate_base_newer
[04:01:49] [PASSED] pf_negotiate_base_next
[04:01:49] [SKIPPED] pf_negotiate_base_older
[04:01:49] [PASSED] pf_negotiate_base_prev
[04:01:49] [PASSED] pf_negotiate_latest_match
[04:01:49] [PASSED] pf_negotiate_latest_newer
[04:01:49] [PASSED] pf_negotiate_latest_next
[04:01:49] [SKIPPED] pf_negotiate_latest_older
[04:01:49] [SKIPPED] pf_negotiate_latest_prev
[04:01:49] =================== [PASSED] pf_service ====================
[04:01:49] ================= xe_guc_g2g (2 subtests) ==================
[04:01:49] ============== xe_live_guc_g2g_kunit_default  ==============
[04:01:49] ========= [SKIPPED] xe_live_guc_g2g_kunit_default ==========
[04:01:49] ============== xe_live_guc_g2g_kunit_allmem  ===============
[04:01:49] ========== [SKIPPED] xe_live_guc_g2g_kunit_allmem ==========
[04:01:49] =================== [SKIPPED] xe_guc_g2g ===================
[04:01:49] =================== xe_mocs (2 subtests) ===================
[04:01:49] ================ xe_live_mocs_kernel_kunit  ================
[04:01:49] =========== [SKIPPED] xe_live_mocs_kernel_kunit ============
[04:01:49] ================ xe_live_mocs_reset_kunit  =================
[04:01:49] ============ [SKIPPED] xe_live_mocs_reset_kunit ============
[04:01:49] ==================== [SKIPPED] xe_mocs =====================
[04:01:49] ================= xe_migrate (2 subtests) ==================
[04:01:49] ================= xe_migrate_sanity_kunit  =================
[04:01:49] ============ [SKIPPED] xe_migrate_sanity_kunit =============
[04:01:49] ================== xe_validate_ccs_kunit  ==================
[04:01:49] ============= [SKIPPED] xe_validate_ccs_kunit ==============
[04:01:49] =================== [SKIPPED] xe_migrate ===================
[04:01:49] ================== xe_dma_buf (1 subtest) ==================
[04:01:49] ==================== xe_dma_buf_kunit  =====================
[04:01:49] ================ [SKIPPED] xe_dma_buf_kunit ================
[04:01:49] =================== [SKIPPED] xe_dma_buf ===================
[04:01:49] ================= xe_bo_shrink (1 subtest) =================
[04:01:49] =================== xe_bo_shrink_kunit  ====================
[04:01:49] =============== [SKIPPED] xe_bo_shrink_kunit ===============
[04:01:49] ================== [SKIPPED] xe_bo_shrink ==================
[04:01:49] ==================== xe_bo (2 subtests) ====================
[04:01:49] ================== xe_ccs_migrate_kunit  ===================
[04:01:49] ============== [SKIPPED] xe_ccs_migrate_kunit ==============
[04:01:49] ==================== xe_bo_evict_kunit  ====================
[04:01:49] =============== [SKIPPED] xe_bo_evict_kunit ================
[04:01:49] ===================== [SKIPPED] xe_bo ======================
[04:01:49] ==================== args (11 subtests) ====================
[04:01:49] [PASSED] count_args_test
[04:01:49] [PASSED] call_args_example
[04:01:49] [PASSED] call_args_test
[04:01:49] [PASSED] drop_first_arg_example
[04:01:49] [PASSED] drop_first_arg_test
[04:01:49] [PASSED] first_arg_example
[04:01:49] [PASSED] first_arg_test
[04:01:49] [PASSED] last_arg_example
[04:01:49] [PASSED] last_arg_test
[04:01:49] [PASSED] pick_arg_example
[04:01:49] [PASSED] sep_comma_example
[04:01:49] ====================== [PASSED] args =======================
[04:01:49] =================== xe_pci (3 subtests) ====================
[04:01:49] ==================== check_graphics_ip  ====================
[04:01:49] [PASSED] 12.00 Xe_LP
[04:01:49] [PASSED] 12.10 Xe_LP+
[04:01:49] [PASSED] 12.55 Xe_HPG
[04:01:49] [PASSED] 12.60 Xe_HPC
[04:01:49] [PASSED] 12.70 Xe_LPG
[04:01:49] [PASSED] 12.71 Xe_LPG
[04:01:49] [PASSED] 12.74 Xe_LPG+
[04:01:49] [PASSED] 20.01 Xe2_HPG
[04:01:49] [PASSED] 20.02 Xe2_HPG
[04:01:49] [PASSED] 20.04 Xe2_LPG
[04:01:49] [PASSED] 30.00 Xe3_LPG
[04:01:49] [PASSED] 30.01 Xe3_LPG
[04:01:49] [PASSED] 30.03 Xe3_LPG
[04:01:49] [PASSED] 30.04 Xe3_LPG
[04:01:49] [PASSED] 30.05 Xe3_LPG
[04:01:49] [PASSED] 35.11 Xe3p_XPC
[04:01:49] ================ [PASSED] check_graphics_ip ================
[04:01:49] ===================== check_media_ip  ======================
[04:01:49] [PASSED] 12.00 Xe_M
[04:01:49] [PASSED] 12.55 Xe_HPM
[04:01:49] [PASSED] 13.00 Xe_LPM+
[04:01:49] [PASSED] 13.01 Xe2_HPM
[04:01:49] [PASSED] 20.00 Xe2_LPM
[04:01:49] [PASSED] 30.00 Xe3_LPM
[04:01:49] [PASSED] 30.02 Xe3_LPM
[04:01:49] [PASSED] 35.00 Xe3p_LPM
[04:01:49] [PASSED] 35.03 Xe3p_HPM
[04:01:49] ================= [PASSED] check_media_ip ==================
[04:01:49] =================== check_platform_desc  ===================
[04:01:49] [PASSED] 0x9A60 (TIGERLAKE)
[04:01:49] [PASSED] 0x9A68 (TIGERLAKE)
[04:01:49] [PASSED] 0x9A70 (TIGERLAKE)
[04:01:49] [PASSED] 0x9A40 (TIGERLAKE)
[04:01:49] [PASSED] 0x9A49 (TIGERLAKE)
[04:01:49] [PASSED] 0x9A59 (TIGERLAKE)
[04:01:49] [PASSED] 0x9A78 (TIGERLAKE)
[04:01:49] [PASSED] 0x9AC0 (TIGERLAKE)
[04:01:49] [PASSED] 0x9AC9 (TIGERLAKE)
[04:01:49] [PASSED] 0x9AD9 (TIGERLAKE)
[04:01:49] [PASSED] 0x9AF8 (TIGERLAKE)
[04:01:49] [PASSED] 0x4C80 (ROCKETLAKE)
[04:01:49] [PASSED] 0x4C8A (ROCKETLAKE)
[04:01:49] [PASSED] 0x4C8B (ROCKETLAKE)
[04:01:49] [PASSED] 0x4C8C (ROCKETLAKE)
[04:01:49] [PASSED] 0x4C90 (ROCKETLAKE)
[04:01:49] [PASSED] 0x4C9A (ROCKETLAKE)
[04:01:49] [PASSED] 0x4680 (ALDERLAKE_S)
[04:01:49] [PASSED] 0x4682 (ALDERLAKE_S)
[04:01:49] [PASSED] 0x4688 (ALDERLAKE_S)
[04:01:49] [PASSED] 0x468A (ALDERLAKE_S)
[04:01:49] [PASSED] 0x468B (ALDERLAKE_S)
[04:01:49] [PASSED] 0x4690 (ALDERLAKE_S)
[04:01:49] [PASSED] 0x4692 (ALDERLAKE_S)
[04:01:49] [PASSED] 0x4693 (ALDERLAKE_S)
[04:01:49] [PASSED] 0x46A0 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46A1 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46A2 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46A3 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46A6 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46A8 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46AA (ALDERLAKE_P)
[04:01:49] [PASSED] 0x462A (ALDERLAKE_P)
[04:01:49] [PASSED] 0x4626 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x4628 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46B0 (ALDERLAKE_P)
stty: 'standard input': Inappropriate ioctl for device
[04:01:49] [PASSED] 0x46B1 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46B2 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46B3 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46C0 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46C1 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46C2 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46C3 (ALDERLAKE_P)
[04:01:49] [PASSED] 0x46D0 (ALDERLAKE_N)
[04:01:49] [PASSED] 0x46D1 (ALDERLAKE_N)
[04:01:49] [PASSED] 0x46D2 (ALDERLAKE_N)
[04:01:49] [PASSED] 0x46D3 (ALDERLAKE_N)
[04:01:49] [PASSED] 0x46D4 (ALDERLAKE_N)
[04:01:49] [PASSED] 0xA721 (ALDERLAKE_P)
[04:01:49] [PASSED] 0xA7A1 (ALDERLAKE_P)
[04:01:49] [PASSED] 0xA7A9 (ALDERLAKE_P)
[04:01:49] [PASSED] 0xA7AC (ALDERLAKE_P)
[04:01:49] [PASSED] 0xA7AD (ALDERLAKE_P)
[04:01:49] [PASSED] 0xA720 (ALDERLAKE_P)
[04:01:49] [PASSED] 0xA7A0 (ALDERLAKE_P)
[04:01:49] [PASSED] 0xA7A8 (ALDERLAKE_P)
[04:01:49] [PASSED] 0xA7AA (ALDERLAKE_P)
[04:01:49] [PASSED] 0xA7AB (ALDERLAKE_P)
[04:01:49] [PASSED] 0xA780 (ALDERLAKE_S)
[04:01:49] [PASSED] 0xA781 (ALDERLAKE_S)
[04:01:49] [PASSED] 0xA782 (ALDERLAKE_S)
[04:01:49] [PASSED] 0xA783 (ALDERLAKE_S)
[04:01:49] [PASSED] 0xA788 (ALDERLAKE_S)
[04:01:49] [PASSED] 0xA789 (ALDERLAKE_S)
[04:01:49] [PASSED] 0xA78A (ALDERLAKE_S)
[04:01:49] [PASSED] 0xA78B (ALDERLAKE_S)
[04:01:49] [PASSED] 0x4905 (DG1)
[04:01:49] [PASSED] 0x4906 (DG1)
[04:01:49] [PASSED] 0x4907 (DG1)
[04:01:49] [PASSED] 0x4908 (DG1)
[04:01:49] [PASSED] 0x4909 (DG1)
[04:01:49] [PASSED] 0x56C0 (DG2)
[04:01:49] [PASSED] 0x56C2 (DG2)
[04:01:49] [PASSED] 0x56C1 (DG2)
[04:01:49] [PASSED] 0x7D51 (METEORLAKE)
[04:01:49] [PASSED] 0x7DD1 (METEORLAKE)
[04:01:49] [PASSED] 0x7D41 (METEORLAKE)
[04:01:49] [PASSED] 0x7D67 (METEORLAKE)
[04:01:49] [PASSED] 0xB640 (METEORLAKE)
[04:01:49] [PASSED] 0x56A0 (DG2)
[04:01:49] [PASSED] 0x56A1 (DG2)
[04:01:49] [PASSED] 0x56A2 (DG2)
[04:01:49] [PASSED] 0x56BE (DG2)
[04:01:49] [PASSED] 0x56BF (DG2)
[04:01:49] [PASSED] 0x5690 (DG2)
[04:01:49] [PASSED] 0x5691 (DG2)
[04:01:49] [PASSED] 0x5692 (DG2)
[04:01:49] [PASSED] 0x56A5 (DG2)
[04:01:49] [PASSED] 0x56A6 (DG2)
[04:01:49] [PASSED] 0x56B0 (DG2)
[04:01:49] [PASSED] 0x56B1 (DG2)
[04:01:49] [PASSED] 0x56BA (DG2)
[04:01:49] [PASSED] 0x56BB (DG2)
[04:01:49] [PASSED] 0x56BC (DG2)
[04:01:49] [PASSED] 0x56BD (DG2)
[04:01:49] [PASSED] 0x5693 (DG2)
[04:01:49] [PASSED] 0x5694 (DG2)
[04:01:49] [PASSED] 0x5695 (DG2)
[04:01:49] [PASSED] 0x56A3 (DG2)
[04:01:49] [PASSED] 0x56A4 (DG2)
[04:01:49] [PASSED] 0x56B2 (DG2)
[04:01:49] [PASSED] 0x56B3 (DG2)
[04:01:49] [PASSED] 0x5696 (DG2)
[04:01:49] [PASSED] 0x5697 (DG2)
[04:01:49] [PASSED] 0xB69 (PVC)
[04:01:49] [PASSED] 0xB6E (PVC)
[04:01:49] [PASSED] 0xBD4 (PVC)
[04:01:49] [PASSED] 0xBD5 (PVC)
[04:01:49] [PASSED] 0xBD6 (PVC)
[04:01:49] [PASSED] 0xBD7 (PVC)
[04:01:49] [PASSED] 0xBD8 (PVC)
[04:01:49] [PASSED] 0xBD9 (PVC)
[04:01:49] [PASSED] 0xBDA (PVC)
[04:01:49] [PASSED] 0xBDB (PVC)
[04:01:49] [PASSED] 0xBE0 (PVC)
[04:01:49] [PASSED] 0xBE1 (PVC)
[04:01:49] [PASSED] 0xBE5 (PVC)
[04:01:49] [PASSED] 0x7D40 (METEORLAKE)
[04:01:49] [PASSED] 0x7D45 (METEORLAKE)
[04:01:49] [PASSED] 0x7D55 (METEORLAKE)
[04:01:49] [PASSED] 0x7D60 (METEORLAKE)
[04:01:49] [PASSED] 0x7DD5 (METEORLAKE)
[04:01:49] [PASSED] 0x6420 (LUNARLAKE)
[04:01:49] [PASSED] 0x64A0 (LUNARLAKE)
[04:01:49] [PASSED] 0x64B0 (LUNARLAKE)
[04:01:49] [PASSED] 0xE202 (BATTLEMAGE)
[04:01:49] [PASSED] 0xE209 (BATTLEMAGE)
[04:01:49] [PASSED] 0xE20B (BATTLEMAGE)
[04:01:49] [PASSED] 0xE20C (BATTLEMAGE)
[04:01:49] [PASSED] 0xE20D (BATTLEMAGE)
[04:01:49] [PASSED] 0xE210 (BATTLEMAGE)
[04:01:49] [PASSED] 0xE211 (BATTLEMAGE)
[04:01:49] [PASSED] 0xE212 (BATTLEMAGE)
[04:01:49] [PASSED] 0xE216 (BATTLEMAGE)
[04:01:49] [PASSED] 0xE220 (BATTLEMAGE)
[04:01:49] [PASSED] 0xE221 (BATTLEMAGE)
[04:01:49] [PASSED] 0xE222 (BATTLEMAGE)
[04:01:49] [PASSED] 0xE223 (BATTLEMAGE)
[04:01:49] [PASSED] 0xB080 (PANTHERLAKE)
[04:01:49] [PASSED] 0xB081 (PANTHERLAKE)
[04:01:49] [PASSED] 0xB082 (PANTHERLAKE)
[04:01:49] [PASSED] 0xB083 (PANTHERLAKE)
[04:01:49] [PASSED] 0xB084 (PANTHERLAKE)
[04:01:49] [PASSED] 0xB085 (PANTHERLAKE)
[04:01:49] [PASSED] 0xB086 (PANTHERLAKE)
[04:01:49] [PASSED] 0xB087 (PANTHERLAKE)
[04:01:49] [PASSED] 0xB08F (PANTHERLAKE)
[04:01:49] [PASSED] 0xB090 (PANTHERLAKE)
[04:01:49] [PASSED] 0xB0A0 (PANTHERLAKE)
[04:01:49] [PASSED] 0xB0B0 (PANTHERLAKE)
[04:01:49] [PASSED] 0xD740 (NOVALAKE_S)
[04:01:49] [PASSED] 0xD741 (NOVALAKE_S)
[04:01:49] [PASSED] 0xD742 (NOVALAKE_S)
[04:01:49] [PASSED] 0xD743 (NOVALAKE_S)
[04:01:49] [PASSED] 0xD744 (NOVALAKE_S)
[04:01:49] [PASSED] 0xD745 (NOVALAKE_S)
[04:01:49] [PASSED] 0x674C (CRESCENTISLAND)
[04:01:49] [PASSED] 0xFD80 (PANTHERLAKE)
[04:01:49] [PASSED] 0xFD81 (PANTHERLAKE)
[04:01:49] =============== [PASSED] check_platform_desc ===============
[04:01:49] ===================== [PASSED] xe_pci ======================
[04:01:49] =================== xe_rtp (2 subtests) ====================
[04:01:49] =============== xe_rtp_process_to_sr_tests  ================
[04:01:49] [PASSED] coalesce-same-reg
[04:01:49] [PASSED] no-match-no-add
[04:01:49] [PASSED] match-or
[04:01:49] [PASSED] match-or-xfail
[04:01:49] [PASSED] no-match-no-add-multiple-rules
[04:01:49] [PASSED] two-regs-two-entries
[04:01:49] [PASSED] clr-one-set-other
[04:01:49] [PASSED] set-field
[04:01:49] [PASSED] conflict-duplicate
[04:01:49] [PASSED] conflict-not-disjoint
[04:01:49] [PASSED] conflict-reg-type
[04:01:49] =========== [PASSED] xe_rtp_process_to_sr_tests ============
[04:01:49] ================== xe_rtp_process_tests  ===================
[04:01:49] [PASSED] active1
[04:01:49] [PASSED] active2
[04:01:49] [PASSED] active-inactive
[04:01:49] [PASSED] inactive-active
[04:01:49] [PASSED] inactive-1st_or_active-inactive
[04:01:49] [PASSED] inactive-2nd_or_active-inactive
[04:01:49] [PASSED] inactive-last_or_active-inactive
[04:01:49] [PASSED] inactive-no_or_active-inactive
[04:01:49] ============== [PASSED] xe_rtp_process_tests ===============
[04:01:49] ===================== [PASSED] xe_rtp ======================
[04:01:49] ==================== xe_wa (1 subtest) =====================
[04:01:49] ======================== xe_wa_gt  =========================
[04:01:49] [PASSED] TIGERLAKE B0
[04:01:49] [PASSED] DG1 A0
[04:01:49] [PASSED] DG1 B0
[04:01:49] [PASSED] ALDERLAKE_S A0
[04:01:49] [PASSED] ALDERLAKE_S B0
[04:01:49] [PASSED] ALDERLAKE_S C0
[04:01:49] [PASSED] ALDERLAKE_S D0
[04:01:49] [PASSED] ALDERLAKE_P A0
[04:01:49] [PASSED] ALDERLAKE_P B0
[04:01:49] [PASSED] ALDERLAKE_P C0
[04:01:49] [PASSED] ALDERLAKE_S RPLS D0
[04:01:49] [PASSED] ALDERLAKE_P RPLU E0
[04:01:49] [PASSED] DG2 G10 C0
[04:01:49] [PASSED] DG2 G11 B1
[04:01:49] [PASSED] DG2 G12 A1
[04:01:49] [PASSED] METEORLAKE 12.70(Xe_LPG) A0 13.00(Xe_LPM+) A0
[04:01:49] [PASSED] METEORLAKE 12.71(Xe_LPG) A0 13.00(Xe_LPM+) A0
[04:01:49] [PASSED] METEORLAKE 12.74(Xe_LPG+) A0 13.00(Xe_LPM+) A0
[04:01:49] [PASSED] LUNARLAKE 20.04(Xe2_LPG) A0 20.00(Xe2_LPM) A0
[04:01:49] [PASSED] LUNARLAKE 20.04(Xe2_LPG) B0 20.00(Xe2_LPM) A0
[04:01:49] [PASSED] BATTLEMAGE 20.01(Xe2_HPG) A0 13.01(Xe2_HPM) A1
[04:01:49] [PASSED] PANTHERLAKE 30.00(Xe3_LPG) A0 30.00(Xe3_LPM) A0
[04:01:49] ==================== [PASSED] xe_wa_gt =====================
[04:01:49] ====================== [PASSED] xe_wa ======================
[04:01:49] ============================================================
[04:01:49] Testing complete. Ran 510 tests: passed: 492, skipped: 18
[04:01:49] Elapsed time: 35.100s total, 4.276s configuring, 30.308s building, 0.470s running

+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/tests/.kunitconfig
[04:01:49] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[04:01:51] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[04:02:16] Starting KUnit Kernel (1/1)...
[04:02:16] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[04:02:16] ============ drm_test_pick_cmdline (2 subtests) ============
[04:02:16] [PASSED] drm_test_pick_cmdline_res_1920_1080_60
[04:02:16] =============== drm_test_pick_cmdline_named  ===============
[04:02:16] [PASSED] NTSC
[04:02:16] [PASSED] NTSC-J
[04:02:16] [PASSED] PAL
[04:02:16] [PASSED] PAL-M
[04:02:16] =========== [PASSED] drm_test_pick_cmdline_named ===========
[04:02:16] ============== [PASSED] drm_test_pick_cmdline ==============
[04:02:16] == drm_test_atomic_get_connector_for_encoder (1 subtest) ===
[04:02:16] [PASSED] drm_test_drm_atomic_get_connector_for_encoder
[04:02:16] ==== [PASSED] drm_test_atomic_get_connector_for_encoder ====
[04:02:16] =========== drm_validate_clone_mode (2 subtests) ===========
[04:02:16] ============== drm_test_check_in_clone_mode  ===============
[04:02:16] [PASSED] in_clone_mode
[04:02:16] [PASSED] not_in_clone_mode
[04:02:16] ========== [PASSED] drm_test_check_in_clone_mode ===========
[04:02:16] =============== drm_test_check_valid_clones  ===============
[04:02:16] [PASSED] not_in_clone_mode
[04:02:16] [PASSED] valid_clone
[04:02:16] [PASSED] invalid_clone
[04:02:16] =========== [PASSED] drm_test_check_valid_clones ===========
[04:02:16] ============= [PASSED] drm_validate_clone_mode =============
[04:02:16] ============= drm_validate_modeset (1 subtest) =============
[04:02:16] [PASSED] drm_test_check_connector_changed_modeset
[04:02:16] ============== [PASSED] drm_validate_modeset ===============
[04:02:16] ====== drm_test_bridge_get_current_state (2 subtests) ======
[04:02:16] [PASSED] drm_test_drm_bridge_get_current_state_atomic
[04:02:16] [PASSED] drm_test_drm_bridge_get_current_state_legacy
[04:02:16] ======== [PASSED] drm_test_bridge_get_current_state ========
[04:02:16] ====== drm_test_bridge_helper_reset_crtc (3 subtests) ======
[04:02:16] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic
[04:02:16] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic_disabled
[04:02:16] [PASSED] drm_test_drm_bridge_helper_reset_crtc_legacy
[04:02:16] ======== [PASSED] drm_test_bridge_helper_reset_crtc ========
[04:02:16] ============== drm_bridge_alloc (2 subtests) ===============
[04:02:16] [PASSED] drm_test_drm_bridge_alloc_basic
[04:02:16] [PASSED] drm_test_drm_bridge_alloc_get_put
[04:02:16] ================ [PASSED] drm_bridge_alloc =================
[04:02:16] ================== drm_buddy (8 subtests) ==================
[04:02:16] [PASSED] drm_test_buddy_alloc_limit
[04:02:16] [PASSED] drm_test_buddy_alloc_optimistic
[04:02:16] [PASSED] drm_test_buddy_alloc_pessimistic
[04:02:16] [PASSED] drm_test_buddy_alloc_pathological
[04:02:16] [PASSED] drm_test_buddy_alloc_contiguous
[04:02:16] [PASSED] drm_test_buddy_alloc_clear
[04:02:16] [PASSED] drm_test_buddy_alloc_range_bias
[04:02:16] [PASSED] drm_test_buddy_fragmentation_performance
[04:02:16] ==================== [PASSED] drm_buddy ====================
[04:02:16] ============= drm_cmdline_parser (40 subtests) =============
[04:02:16] [PASSED] drm_test_cmdline_force_d_only
[04:02:16] [PASSED] drm_test_cmdline_force_D_only_dvi
[04:02:16] [PASSED] drm_test_cmdline_force_D_only_hdmi
[04:02:16] [PASSED] drm_test_cmdline_force_D_only_not_digital
[04:02:16] [PASSED] drm_test_cmdline_force_e_only
[04:02:16] [PASSED] drm_test_cmdline_res
[04:02:16] [PASSED] drm_test_cmdline_res_vesa
[04:02:16] [PASSED] drm_test_cmdline_res_vesa_rblank
[04:02:16] [PASSED] drm_test_cmdline_res_rblank
[04:02:16] [PASSED] drm_test_cmdline_res_bpp
[04:02:16] [PASSED] drm_test_cmdline_res_refresh
[04:02:16] [PASSED] drm_test_cmdline_res_bpp_refresh
[04:02:16] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced
[04:02:16] [PASSED] drm_test_cmdline_res_bpp_refresh_margins
[04:02:16] [PASSED] drm_test_cmdline_res_bpp_refresh_force_off
[04:02:16] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on
[04:02:16] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_analog
[04:02:16] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_digital
[04:02:16] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced_margins_force_on
[04:02:16] [PASSED] drm_test_cmdline_res_margins_force_on
[04:02:16] [PASSED] drm_test_cmdline_res_vesa_margins
[04:02:16] [PASSED] drm_test_cmdline_name
[04:02:16] [PASSED] drm_test_cmdline_name_bpp
[04:02:16] [PASSED] drm_test_cmdline_name_option
[04:02:16] [PASSED] drm_test_cmdline_name_bpp_option
[04:02:16] [PASSED] drm_test_cmdline_rotate_0
[04:02:16] [PASSED] drm_test_cmdline_rotate_90
[04:02:16] [PASSED] drm_test_cmdline_rotate_180
[04:02:16] [PASSED] drm_test_cmdline_rotate_270
[04:02:16] [PASSED] drm_test_cmdline_hmirror
[04:02:16] [PASSED] drm_test_cmdline_vmirror
[04:02:16] [PASSED] drm_test_cmdline_margin_options
[04:02:16] [PASSED] drm_test_cmdline_multiple_options
[04:02:16] [PASSED] drm_test_cmdline_bpp_extra_and_option
[04:02:16] [PASSED] drm_test_cmdline_extra_and_option
[04:02:16] [PASSED] drm_test_cmdline_freestanding_options
[04:02:16] [PASSED] drm_test_cmdline_freestanding_force_e_and_options
[04:02:16] [PASSED] drm_test_cmdline_panel_orientation
[04:02:16] ================ drm_test_cmdline_invalid  =================
[04:02:16] [PASSED] margin_only
[04:02:16] [PASSED] interlace_only
[04:02:16] [PASSED] res_missing_x
[04:02:16] [PASSED] res_missing_y
[04:02:16] [PASSED] res_bad_y
[04:02:16] [PASSED] res_missing_y_bpp
[04:02:16] [PASSED] res_bad_bpp
[04:02:16] [PASSED] res_bad_refresh
[04:02:16] [PASSED] res_bpp_refresh_force_on_off
[04:02:16] [PASSED] res_invalid_mode
[04:02:16] [PASSED] res_bpp_wrong_place_mode
[04:02:16] [PASSED] name_bpp_refresh
[04:02:16] [PASSED] name_refresh
[04:02:16] [PASSED] name_refresh_wrong_mode
[04:02:16] [PASSED] name_refresh_invalid_mode
[04:02:16] [PASSED] rotate_multiple
[04:02:16] [PASSED] rotate_invalid_val
[04:02:16] [PASSED] rotate_truncated
[04:02:16] [PASSED] invalid_option
[04:02:16] [PASSED] invalid_tv_option
[04:02:16] [PASSED] truncated_tv_option
[04:02:16] ============ [PASSED] drm_test_cmdline_invalid =============
[04:02:16] =============== drm_test_cmdline_tv_options  ===============
[04:02:16] [PASSED] NTSC
[04:02:16] [PASSED] NTSC_443
[04:02:16] [PASSED] NTSC_J
[04:02:16] [PASSED] PAL
[04:02:16] [PASSED] PAL_M
[04:02:16] [PASSED] PAL_N
[04:02:16] [PASSED] SECAM
[04:02:16] [PASSED] MONO_525
[04:02:16] [PASSED] MONO_625
[04:02:16] =========== [PASSED] drm_test_cmdline_tv_options ===========
[04:02:16] =============== [PASSED] drm_cmdline_parser ================
[04:02:16] ========== drmm_connector_hdmi_init (20 subtests) ==========
[04:02:16] [PASSED] drm_test_connector_hdmi_init_valid
[04:02:16] [PASSED] drm_test_connector_hdmi_init_bpc_8
[04:02:16] [PASSED] drm_test_connector_hdmi_init_bpc_10
[04:02:16] [PASSED] drm_test_connector_hdmi_init_bpc_12
[04:02:16] [PASSED] drm_test_connector_hdmi_init_bpc_invalid
[04:02:16] [PASSED] drm_test_connector_hdmi_init_bpc_null
[04:02:16] [PASSED] drm_test_connector_hdmi_init_formats_empty
[04:02:16] [PASSED] drm_test_connector_hdmi_init_formats_no_rgb
[04:02:16] === drm_test_connector_hdmi_init_formats_yuv420_allowed  ===
[04:02:16] [PASSED] supported_formats=0x9 yuv420_allowed=1
[04:02:16] [PASSED] supported_formats=0x9 yuv420_allowed=0
[04:02:16] [PASSED] supported_formats=0x3 yuv420_allowed=1
[04:02:16] [PASSED] supported_formats=0x3 yuv420_allowed=0
[04:02:16] === [PASSED] drm_test_connector_hdmi_init_formats_yuv420_allowed ===
[04:02:16] [PASSED] drm_test_connector_hdmi_init_null_ddc
[04:02:16] [PASSED] drm_test_connector_hdmi_init_null_product
[04:02:16] [PASSED] drm_test_connector_hdmi_init_null_vendor
[04:02:16] [PASSED] drm_test_connector_hdmi_init_product_length_exact
[04:02:16] [PASSED] drm_test_connector_hdmi_init_product_length_too_long
[04:02:16] [PASSED] drm_test_connector_hdmi_init_product_valid
[04:02:16] [PASSED] drm_test_connector_hdmi_init_vendor_length_exact
[04:02:16] [PASSED] drm_test_connector_hdmi_init_vendor_length_too_long
[04:02:16] [PASSED] drm_test_connector_hdmi_init_vendor_valid
[04:02:16] ========= drm_test_connector_hdmi_init_type_valid  =========
[04:02:16] [PASSED] HDMI-A
[04:02:16] [PASSED] HDMI-B
[04:02:16] ===== [PASSED] drm_test_connector_hdmi_init_type_valid =====
[04:02:16] ======== drm_test_connector_hdmi_init_type_invalid  ========
[04:02:16] [PASSED] Unknown
[04:02:16] [PASSED] VGA
[04:02:16] [PASSED] DVI-I
[04:02:16] [PASSED] DVI-D
[04:02:16] [PASSED] DVI-A
[04:02:16] [PASSED] Composite
[04:02:16] [PASSED] SVIDEO
[04:02:16] [PASSED] LVDS
[04:02:16] [PASSED] Component
[04:02:16] [PASSED] DIN
[04:02:16] [PASSED] DP
[04:02:16] [PASSED] TV
[04:02:16] [PASSED] eDP
[04:02:16] [PASSED] Virtual
[04:02:16] [PASSED] DSI
[04:02:16] [PASSED] DPI
[04:02:16] [PASSED] Writeback
[04:02:16] [PASSED] SPI
[04:02:16] [PASSED] USB
[04:02:16] ==== [PASSED] drm_test_connector_hdmi_init_type_invalid ====
[04:02:16] ============ [PASSED] drmm_connector_hdmi_init =============
[04:02:16] ============= drmm_connector_init (3 subtests) =============
[04:02:16] [PASSED] drm_test_drmm_connector_init
[04:02:16] [PASSED] drm_test_drmm_connector_init_null_ddc
[04:02:16] ========= drm_test_drmm_connector_init_type_valid  =========
[04:02:16] [PASSED] Unknown
[04:02:16] [PASSED] VGA
[04:02:16] [PASSED] DVI-I
[04:02:16] [PASSED] DVI-D
[04:02:16] [PASSED] DVI-A
[04:02:16] [PASSED] Composite
[04:02:16] [PASSED] SVIDEO
[04:02:16] [PASSED] LVDS
[04:02:16] [PASSED] Component
[04:02:16] [PASSED] DIN
[04:02:16] [PASSED] DP
[04:02:16] [PASSED] HDMI-A
[04:02:16] [PASSED] HDMI-B
[04:02:16] [PASSED] TV
[04:02:16] [PASSED] eDP
[04:02:16] [PASSED] Virtual
[04:02:16] [PASSED] DSI
[04:02:16] [PASSED] DPI
[04:02:16] [PASSED] Writeback
[04:02:16] [PASSED] SPI
[04:02:16] [PASSED] USB
[04:02:16] ===== [PASSED] drm_test_drmm_connector_init_type_valid =====
[04:02:16] =============== [PASSED] drmm_connector_init ===============
[04:02:16] ========= drm_connector_dynamic_init (6 subtests) ==========
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_init
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_init_null_ddc
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_init_not_added
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_init_properties
[04:02:16] ===== drm_test_drm_connector_dynamic_init_type_valid  ======
[04:02:16] [PASSED] Unknown
[04:02:16] [PASSED] VGA
[04:02:16] [PASSED] DVI-I
[04:02:16] [PASSED] DVI-D
[04:02:16] [PASSED] DVI-A
[04:02:16] [PASSED] Composite
[04:02:16] [PASSED] SVIDEO
[04:02:16] [PASSED] LVDS
[04:02:16] [PASSED] Component
[04:02:16] [PASSED] DIN
[04:02:16] [PASSED] DP
[04:02:16] [PASSED] HDMI-A
[04:02:16] [PASSED] HDMI-B
[04:02:16] [PASSED] TV
[04:02:16] [PASSED] eDP
[04:02:16] [PASSED] Virtual
[04:02:16] [PASSED] DSI
[04:02:16] [PASSED] DPI
[04:02:16] [PASSED] Writeback
[04:02:16] [PASSED] SPI
[04:02:16] [PASSED] USB
[04:02:16] = [PASSED] drm_test_drm_connector_dynamic_init_type_valid ==
[04:02:16] ======== drm_test_drm_connector_dynamic_init_name  =========
[04:02:16] [PASSED] Unknown
[04:02:16] [PASSED] VGA
[04:02:16] [PASSED] DVI-I
[04:02:16] [PASSED] DVI-D
[04:02:16] [PASSED] DVI-A
[04:02:16] [PASSED] Composite
[04:02:16] [PASSED] SVIDEO
[04:02:16] [PASSED] LVDS
[04:02:16] [PASSED] Component
[04:02:16] [PASSED] DIN
[04:02:16] [PASSED] DP
[04:02:16] [PASSED] HDMI-A
[04:02:16] [PASSED] HDMI-B
[04:02:16] [PASSED] TV
[04:02:16] [PASSED] eDP
[04:02:16] [PASSED] Virtual
[04:02:16] [PASSED] DSI
[04:02:16] [PASSED] DPI
[04:02:16] [PASSED] Writeback
[04:02:16] [PASSED] SPI
[04:02:16] [PASSED] USB
[04:02:16] ==== [PASSED] drm_test_drm_connector_dynamic_init_name =====
[04:02:16] =========== [PASSED] drm_connector_dynamic_init ============
[04:02:16] ==== drm_connector_dynamic_register_early (4 subtests) =====
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_register_early_on_list
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_register_early_defer
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_register_early_no_init
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_register_early_no_mode_object
[04:02:16] ====== [PASSED] drm_connector_dynamic_register_early =======
[04:02:16] ======= drm_connector_dynamic_register (7 subtests) ========
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_register_on_list
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_register_no_defer
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_register_no_init
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_register_mode_object
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_register_sysfs
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_register_sysfs_name
[04:02:16] [PASSED] drm_test_drm_connector_dynamic_register_debugfs
[04:02:16] ========= [PASSED] drm_connector_dynamic_register ==========
[04:02:16] = drm_connector_attach_broadcast_rgb_property (2 subtests) =
[04:02:16] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property
[04:02:16] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector
[04:02:16] === [PASSED] drm_connector_attach_broadcast_rgb_property ===
[04:02:16] ========== drm_get_tv_mode_from_name (2 subtests) ==========
[04:02:16] ========== drm_test_get_tv_mode_from_name_valid  ===========
[04:02:16] [PASSED] NTSC
[04:02:16] [PASSED] NTSC-443
[04:02:16] [PASSED] NTSC-J
[04:02:16] [PASSED] PAL
[04:02:16] [PASSED] PAL-M
[04:02:16] [PASSED] PAL-N
[04:02:16] [PASSED] SECAM
[04:02:16] [PASSED] Mono
[04:02:16] ====== [PASSED] drm_test_get_tv_mode_from_name_valid =======
[04:02:16] [PASSED] drm_test_get_tv_mode_from_name_truncated
[04:02:16] ============ [PASSED] drm_get_tv_mode_from_name ============
[04:02:16] = drm_test_connector_hdmi_compute_mode_clock (12 subtests) =
[04:02:16] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb
[04:02:16] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc
[04:02:16] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1
[04:02:16] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc
[04:02:16] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1
[04:02:16] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_double
[04:02:16] = drm_test_connector_hdmi_compute_mode_clock_yuv420_valid  =
[04:02:16] [PASSED] VIC 96
[04:02:16] [PASSED] VIC 97
[04:02:16] [PASSED] VIC 101
[04:02:16] [PASSED] VIC 102
[04:02:16] [PASSED] VIC 106
[04:02:16] [PASSED] VIC 107
[04:02:16] === [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_valid ===
[04:02:16] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc
[04:02:16] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc
[04:02:16] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc
[04:02:16] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc
[04:02:16] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc
[04:02:16] === [PASSED] drm_test_connector_hdmi_compute_mode_clock ====
[04:02:16] == drm_hdmi_connector_get_broadcast_rgb_name (2 subtests) ==
[04:02:16] === drm_test_drm_hdmi_connector_get_broadcast_rgb_name  ====
[04:02:16] [PASSED] Automatic
[04:02:16] [PASSED] Full
[04:02:16] [PASSED] Limited 16:235
[04:02:16] === [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name ===
[04:02:16] [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid
[04:02:16] ==== [PASSED] drm_hdmi_connector_get_broadcast_rgb_name ====
[04:02:16] == drm_hdmi_connector_get_output_format_name (2 subtests) ==
[04:02:16] === drm_test_drm_hdmi_connector_get_output_format_name  ====
[04:02:16] [PASSED] RGB
[04:02:16] [PASSED] YUV 4:2:0
[04:02:16] [PASSED] YUV 4:2:2
[04:02:16] [PASSED] YUV 4:4:4
[04:02:16] === [PASSED] drm_test_drm_hdmi_connector_get_output_format_name ===
[04:02:16] [PASSED] drm_test_drm_hdmi_connector_get_output_format_name_invalid
[04:02:16] ==== [PASSED] drm_hdmi_connector_get_output_format_name ====
[04:02:16] ============= drm_damage_helper (21 subtests) ==============
[04:02:16] [PASSED] drm_test_damage_iter_no_damage
[04:02:16] [PASSED] drm_test_damage_iter_no_damage_fractional_src
[04:02:16] [PASSED] drm_test_damage_iter_no_damage_src_moved
[04:02:16] [PASSED] drm_test_damage_iter_no_damage_fractional_src_moved
[04:02:16] [PASSED] drm_test_damage_iter_no_damage_not_visible
[04:02:16] [PASSED] drm_test_damage_iter_no_damage_no_crtc
[04:02:16] [PASSED] drm_test_damage_iter_no_damage_no_fb
[04:02:16] [PASSED] drm_test_damage_iter_simple_damage
[04:02:16] [PASSED] drm_test_damage_iter_single_damage
[04:02:16] [PASSED] drm_test_damage_iter_single_damage_intersect_src
[04:02:16] [PASSED] drm_test_damage_iter_single_damage_outside_src
[04:02:16] [PASSED] drm_test_damage_iter_single_damage_fractional_src
[04:02:16] [PASSED] drm_test_damage_iter_single_damage_intersect_fractional_src
[04:02:16] [PASSED] drm_test_damage_iter_single_damage_outside_fractional_src
[04:02:16] [PASSED] drm_test_damage_iter_single_damage_src_moved
[04:02:16] [PASSED] drm_test_damage_iter_single_damage_fractional_src_moved
[04:02:16] [PASSED] drm_test_damage_iter_damage
[04:02:16] [PASSED] drm_test_damage_iter_damage_one_intersect
[04:02:16] [PASSED] drm_test_damage_iter_damage_one_outside
[04:02:16] [PASSED] drm_test_damage_iter_damage_src_moved
[04:02:16] [PASSED] drm_test_damage_iter_damage_not_visible
[04:02:16] ================ [PASSED] drm_damage_helper ================
[04:02:16] ============== drm_dp_mst_helper (3 subtests) ==============
[04:02:16] ============== drm_test_dp_mst_calc_pbn_mode  ==============
[04:02:16] [PASSED] Clock 154000 BPP 30 DSC disabled
[04:02:16] [PASSED] Clock 234000 BPP 30 DSC disabled
[04:02:16] [PASSED] Clock 297000 BPP 24 DSC disabled
[04:02:16] [PASSED] Clock 332880 BPP 24 DSC enabled
[04:02:16] [PASSED] Clock 324540 BPP 24 DSC enabled
[04:02:16] ========== [PASSED] drm_test_dp_mst_calc_pbn_mode ==========
[04:02:16] ============== drm_test_dp_mst_calc_pbn_div  ===============
[04:02:16] [PASSED] Link rate 2000000 lane count 4
[04:02:16] [PASSED] Link rate 2000000 lane count 2
[04:02:16] [PASSED] Link rate 2000000 lane count 1
[04:02:16] [PASSED] Link rate 1350000 lane count 4
[04:02:16] [PASSED] Link rate 1350000 lane count 2
[04:02:16] [PASSED] Link rate 1350000 lane count 1
[04:02:16] [PASSED] Link rate 1000000 lane count 4
[04:02:16] [PASSED] Link rate 1000000 lane count 2
[04:02:16] [PASSED] Link rate 1000000 lane count 1
[04:02:16] [PASSED] Link rate 810000 lane count 4
[04:02:16] [PASSED] Link rate 810000 lane count 2
[04:02:16] [PASSED] Link rate 810000 lane count 1
[04:02:16] [PASSED] Link rate 540000 lane count 4
[04:02:16] [PASSED] Link rate 540000 lane count 2
[04:02:16] [PASSED] Link rate 540000 lane count 1
[04:02:16] [PASSED] Link rate 270000 lane count 4
[04:02:16] [PASSED] Link rate 270000 lane count 2
[04:02:16] [PASSED] Link rate 270000 lane count 1
[04:02:16] [PASSED] Link rate 162000 lane count 4
[04:02:16] [PASSED] Link rate 162000 lane count 2
[04:02:16] [PASSED] Link rate 162000 lane count 1
[04:02:16] ========== [PASSED] drm_test_dp_mst_calc_pbn_div ===========
[04:02:16] ========= drm_test_dp_mst_sideband_msg_req_decode  =========
[04:02:16] [PASSED] DP_ENUM_PATH_RESOURCES with port number
[04:02:16] [PASSED] DP_POWER_UP_PHY with port number
[04:02:16] [PASSED] DP_POWER_DOWN_PHY with port number
[04:02:16] [PASSED] DP_ALLOCATE_PAYLOAD with SDP stream sinks
[04:02:16] [PASSED] DP_ALLOCATE_PAYLOAD with port number
[04:02:16] [PASSED] DP_ALLOCATE_PAYLOAD with VCPI
[04:02:16] [PASSED] DP_ALLOCATE_PAYLOAD with PBN
[04:02:16] [PASSED] DP_QUERY_PAYLOAD with port number
[04:02:16] [PASSED] DP_QUERY_PAYLOAD with VCPI
[04:02:16] [PASSED] DP_REMOTE_DPCD_READ with port number
[04:02:16] [PASSED] DP_REMOTE_DPCD_READ with DPCD address
[04:02:16] [PASSED] DP_REMOTE_DPCD_READ with max number of bytes
[04:02:16] [PASSED] DP_REMOTE_DPCD_WRITE with port number
[04:02:16] [PASSED] DP_REMOTE_DPCD_WRITE with DPCD address
[04:02:16] [PASSED] DP_REMOTE_DPCD_WRITE with data array
[04:02:16] [PASSED] DP_REMOTE_I2C_READ with port number
[04:02:16] [PASSED] DP_REMOTE_I2C_READ with I2C device ID
[04:02:16] [PASSED] DP_REMOTE_I2C_READ with transactions array
[04:02:16] [PASSED] DP_REMOTE_I2C_WRITE with port number
[04:02:16] [PASSED] DP_REMOTE_I2C_WRITE with I2C device ID
[04:02:16] [PASSED] DP_REMOTE_I2C_WRITE with data array
[04:02:16] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream ID
[04:02:16] [PASSED] DP_QUERY_STREAM_ENC_STATUS with client ID
[04:02:16] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream event
[04:02:16] [PASSED] DP_QUERY_STREAM_ENC_STATUS with valid stream event
[04:02:16] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream behavior
[04:02:16] [PASSED] DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior
[04:02:16] ===== [PASSED] drm_test_dp_mst_sideband_msg_req_decode =====
[04:02:16] ================ [PASSED] drm_dp_mst_helper ================
[04:02:16] ================== drm_exec (7 subtests) ===================
[04:02:16] [PASSED] sanitycheck
[04:02:16] [PASSED] test_lock
[04:02:16] [PASSED] test_lock_unlock
[04:02:16] [PASSED] test_duplicates
[04:02:16] [PASSED] test_prepare
[04:02:16] [PASSED] test_prepare_array
[04:02:16] [PASSED] test_multiple_loops
[04:02:16] ==================== [PASSED] drm_exec =====================
[04:02:16] =========== drm_format_helper_test (17 subtests) ===========
[04:02:16] ============== drm_test_fb_xrgb8888_to_gray8  ==============
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ========== [PASSED] drm_test_fb_xrgb8888_to_gray8 ==========
[04:02:16] ============= drm_test_fb_xrgb8888_to_rgb332  ==============
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb332 ==========
[04:02:16] ============= drm_test_fb_xrgb8888_to_rgb565  ==============
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb565 ==========
[04:02:16] ============ drm_test_fb_xrgb8888_to_xrgb1555  =============
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ======== [PASSED] drm_test_fb_xrgb8888_to_xrgb1555 =========
[04:02:16] ============ drm_test_fb_xrgb8888_to_argb1555  =============
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ======== [PASSED] drm_test_fb_xrgb8888_to_argb1555 =========
[04:02:16] ============ drm_test_fb_xrgb8888_to_rgba5551  =============
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ======== [PASSED] drm_test_fb_xrgb8888_to_rgba5551 =========
[04:02:16] ============= drm_test_fb_xrgb8888_to_rgb888  ==============
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb888 ==========
[04:02:16] ============= drm_test_fb_xrgb8888_to_bgr888  ==============
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ========= [PASSED] drm_test_fb_xrgb8888_to_bgr888 ==========
[04:02:16] ============ drm_test_fb_xrgb8888_to_argb8888  =============
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ======== [PASSED] drm_test_fb_xrgb8888_to_argb8888 =========
[04:02:16] =========== drm_test_fb_xrgb8888_to_xrgb2101010  ===========
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ======= [PASSED] drm_test_fb_xrgb8888_to_xrgb2101010 =======
[04:02:16] =========== drm_test_fb_xrgb8888_to_argb2101010  ===========
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ======= [PASSED] drm_test_fb_xrgb8888_to_argb2101010 =======
[04:02:16] ============== drm_test_fb_xrgb8888_to_mono  ===============
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ========== [PASSED] drm_test_fb_xrgb8888_to_mono ===========
[04:02:16] ==================== drm_test_fb_swab  =====================
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ================ [PASSED] drm_test_fb_swab =================
[04:02:16] ============ drm_test_fb_xrgb8888_to_xbgr8888  =============
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ======== [PASSED] drm_test_fb_xrgb8888_to_xbgr8888 =========
[04:02:16] ============ drm_test_fb_xrgb8888_to_abgr8888  =============
[04:02:16] [PASSED] single_pixel_source_buffer
[04:02:16] [PASSED] single_pixel_clip_rectangle
[04:02:16] [PASSED] well_known_colors
[04:02:16] [PASSED] destination_pitch
[04:02:16] ======== [PASSED] drm_test_fb_xrgb8888_to_abgr8888 =========
[04:02:16] ================= drm_test_fb_clip_offset  =================
[04:02:16] [PASSED] pass through
[04:02:16] [PASSED] horizontal offset
[04:02:16] [PASSED] vertical offset
[04:02:16] [PASSED] horizontal and vertical offset
[04:02:16] [PASSED] horizontal offset (custom pitch)
[04:02:16] [PASSED] vertical offset (custom pitch)
[04:02:16] [PASSED] horizontal and vertical offset (custom pitch)
[04:02:16] ============= [PASSED] drm_test_fb_clip_offset =============
[04:02:16] =================== drm_test_fb_memcpy  ====================
[04:02:16] [PASSED] single_pixel_source_buffer: XR24 little-endian (0x34325258)
[04:02:16] [PASSED] single_pixel_source_buffer: XRA8 little-endian (0x38415258)
[04:02:16] [PASSED] single_pixel_source_buffer: YU24 little-endian (0x34325559)
[04:02:16] [PASSED] single_pixel_clip_rectangle: XB24 little-endian (0x34324258)
[04:02:16] [PASSED] single_pixel_clip_rectangle: XRA8 little-endian (0x38415258)
[04:02:16] [PASSED] single_pixel_clip_rectangle: YU24 little-endian (0x34325559)
[04:02:16] [PASSED] well_known_colors: XB24 little-endian (0x34324258)
[04:02:16] [PASSED] well_known_colors: XRA8 little-endian (0x38415258)
[04:02:16] [PASSED] well_known_colors: YU24 little-endian (0x34325559)
[04:02:16] [PASSED] destination_pitch: XB24 little-endian (0x34324258)
[04:02:16] [PASSED] destination_pitch: XRA8 little-endian (0x38415258)
[04:02:16] [PASSED] destination_pitch: YU24 little-endian (0x34325559)
[04:02:16] =============== [PASSED] drm_test_fb_memcpy ================
[04:02:16] ============= [PASSED] drm_format_helper_test ==============
[04:02:16] ================= drm_format (18 subtests) =================
[04:02:16] [PASSED] drm_test_format_block_width_invalid
[04:02:16] [PASSED] drm_test_format_block_width_one_plane
[04:02:16] [PASSED] drm_test_format_block_width_two_plane
[04:02:16] [PASSED] drm_test_format_block_width_three_plane
[04:02:16] [PASSED] drm_test_format_block_width_tiled
[04:02:16] [PASSED] drm_test_format_block_height_invalid
[04:02:16] [PASSED] drm_test_format_block_height_one_plane
[04:02:16] [PASSED] drm_test_format_block_height_two_plane
[04:02:16] [PASSED] drm_test_format_block_height_three_plane
[04:02:16] [PASSED] drm_test_format_block_height_tiled
[04:02:16] [PASSED] drm_test_format_min_pitch_invalid
[04:02:16] [PASSED] drm_test_format_min_pitch_one_plane_8bpp
[04:02:16] [PASSED] drm_test_format_min_pitch_one_plane_16bpp
[04:02:16] [PASSED] drm_test_format_min_pitch_one_plane_24bpp
[04:02:16] [PASSED] drm_test_format_min_pitch_one_plane_32bpp
[04:02:16] [PASSED] drm_test_format_min_pitch_two_plane
[04:02:16] [PASSED] drm_test_format_min_pitch_three_plane_8bpp
[04:02:16] [PASSED] drm_test_format_min_pitch_tiled
[04:02:16] =================== [PASSED] drm_format ====================
[04:02:16] ============== drm_framebuffer (10 subtests) ===============
[04:02:16] ========== drm_test_framebuffer_check_src_coords  ==========
[04:02:16] [PASSED] Success: source fits into fb
[04:02:16] [PASSED] Fail: overflowing fb with x-axis coordinate
[04:02:16] [PASSED] Fail: overflowing fb with y-axis coordinate
[04:02:16] [PASSED] Fail: overflowing fb with source width
[04:02:16] [PASSED] Fail: overflowing fb with source height
[04:02:16] ====== [PASSED] drm_test_framebuffer_check_src_coords ======
[04:02:16] [PASSED] drm_test_framebuffer_cleanup
[04:02:16] =============== drm_test_framebuffer_create  ===============
[04:02:16] [PASSED] ABGR8888 normal sizes
[04:02:16] [PASSED] ABGR8888 max sizes
[04:02:16] [PASSED] ABGR8888 pitch greater than min required
[04:02:16] [PASSED] ABGR8888 pitch less than min required
[04:02:16] [PASSED] ABGR8888 Invalid width
[04:02:16] [PASSED] ABGR8888 Invalid buffer handle
[04:02:16] [PASSED] No pixel format
[04:02:16] [PASSED] ABGR8888 Width 0
[04:02:16] [PASSED] ABGR8888 Height 0
[04:02:16] [PASSED] ABGR8888 Out of bound height * pitch combination
[04:02:16] [PASSED] ABGR8888 Large buffer offset
[04:02:16] [PASSED] ABGR8888 Buffer offset for inexistent plane
[04:02:16] [PASSED] ABGR8888 Invalid flag
[04:02:16] [PASSED] ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers
[04:02:16] [PASSED] ABGR8888 Valid buffer modifier
[04:02:16] [PASSED] ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
[04:02:16] [PASSED] ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS
[04:02:16] [PASSED] ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS
[04:02:16] [PASSED] NV12 Normal sizes
[04:02:16] [PASSED] NV12 Max sizes
[04:02:16] [PASSED] NV12 Invalid pitch
[04:02:16] [PASSED] NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag
[04:02:16] [PASSED] NV12 different  modifier per-plane
[04:02:16] [PASSED] NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE
[04:02:16] [PASSED] NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS
[04:02:16] [PASSED] NV12 Modifier for inexistent plane
[04:02:16] [PASSED] NV12 Handle for inexistent plane
[04:02:16] [PASSED] NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS
[04:02:16] [PASSED] YVU420 DRM_MODE_FB_MODIFIERS set without modifier
[04:02:16] [PASSED] YVU420 Normal sizes
[04:02:16] [PASSED] YVU420 Max sizes
[04:02:16] [PASSED] YVU420 Invalid pitch
[04:02:16] [PASSED] YVU420 Different pitches
[04:02:16] [PASSED] YVU420 Different buffer offsets/pitches
[04:02:16] [PASSED] YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS
[04:02:16] [PASSED] YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS
[04:02:16] [PASSED] YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS
[04:02:16] [PASSED] YVU420 Valid modifier
[04:02:16] [PASSED] YVU420 Different modifiers per plane
[04:02:16] [PASSED] YVU420 Modifier for inexistent plane
[04:02:16] [PASSED] YUV420_10BIT Invalid modifier(DRM_FORMAT_MOD_LINEAR)
[04:02:16] [PASSED] X0L2 Normal sizes
[04:02:16] [PASSED] X0L2 Max sizes
[04:02:16] [PASSED] X0L2 Invalid pitch
[04:02:16] [PASSED] X0L2 Pitch greater than minimum required
[04:02:16] [PASSED] X0L2 Handle for inexistent plane
[04:02:16] [PASSED] X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set
[04:02:16] [PASSED] X0L2 Modifier without DRM_MODE_FB_MODIFIERS set
[04:02:16] [PASSED] X0L2 Valid modifier
[04:02:16] [PASSED] X0L2 Modifier for inexistent plane
[04:02:16] =========== [PASSED] drm_test_framebuffer_create ===========
[04:02:16] [PASSED] drm_test_framebuffer_free
[04:02:16] [PASSED] drm_test_framebuffer_init
[04:02:16] [PASSED] drm_test_framebuffer_init_bad_format
[04:02:16] [PASSED] drm_test_framebuffer_init_dev_mismatch
[04:02:16] [PASSED] drm_test_framebuffer_lookup
[04:02:16] [PASSED] drm_test_framebuffer_lookup_inexistent
[04:02:16] [PASSED] drm_test_framebuffer_modifiers_not_supported
[04:02:16] ================= [PASSED] drm_framebuffer =================
[04:02:16] ================ drm_gem_shmem (8 subtests) ================
[04:02:16] [PASSED] drm_gem_shmem_test_obj_create
[04:02:16] [PASSED] drm_gem_shmem_test_obj_create_private
[04:02:16] [PASSED] drm_gem_shmem_test_pin_pages
[04:02:16] [PASSED] drm_gem_shmem_test_vmap
[04:02:16] [PASSED] drm_gem_shmem_test_get_pages_sgt
[04:02:16] [PASSED] drm_gem_shmem_test_get_sg_table
[04:02:16] [PASSED] drm_gem_shmem_test_madvise
[04:02:16] [PASSED] drm_gem_shmem_test_purge
[04:02:16] ================== [PASSED] drm_gem_shmem ==================
[04:02:16] === drm_atomic_helper_connector_hdmi_check (27 subtests) ===
[04:02:16] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode
[04:02:16] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode_vic_1
[04:02:16] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode
[04:02:16] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode_vic_1
[04:02:16] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode
[04:02:16] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode_vic_1
[04:02:16] ====== drm_test_check_broadcast_rgb_cea_mode_yuv420  =======
[04:02:16] [PASSED] Automatic
[04:02:16] [PASSED] Full
[04:02:16] [PASSED] Limited 16:235
[04:02:16] == [PASSED] drm_test_check_broadcast_rgb_cea_mode_yuv420 ===
[04:02:16] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_changed
[04:02:16] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_not_changed
[04:02:16] [PASSED] drm_test_check_disable_connector
[04:02:16] [PASSED] drm_test_check_hdmi_funcs_reject_rate
[04:02:16] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_rgb
[04:02:16] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_yuv420
[04:02:16] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422
[04:02:16] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420
[04:02:16] [PASSED] drm_test_check_driver_unsupported_fallback_yuv420
[04:02:16] [PASSED] drm_test_check_output_bpc_crtc_mode_changed
[04:02:16] [PASSED] drm_test_check_output_bpc_crtc_mode_not_changed
[04:02:16] [PASSED] drm_test_check_output_bpc_dvi
[04:02:16] [PASSED] drm_test_check_output_bpc_format_vic_1
[04:02:16] [PASSED] drm_test_check_output_bpc_format_display_8bpc_only
[04:02:16] [PASSED] drm_test_check_output_bpc_format_display_rgb_only
[04:02:16] [PASSED] drm_test_check_output_bpc_format_driver_8bpc_only
[04:02:16] [PASSED] drm_test_check_output_bpc_format_driver_rgb_only
[04:02:16] [PASSED] drm_test_check_tmds_char_rate_rgb_8bpc
[04:02:16] [PASSED] drm_test_check_tmds_char_rate_rgb_10bpc
[04:02:16] [PASSED] drm_test_check_tmds_char_rate_rgb_12bpc
[04:02:16] ===== [PASSED] drm_atomic_helper_connector_hdmi_check ======
[04:02:16] === drm_atomic_helper_connector_hdmi_reset (6 subtests) ====
[04:02:16] [PASSED] drm_test_check_broadcast_rgb_value
[04:02:16] [PASSED] drm_test_check_bpc_8_value
[04:02:16] [PASSED] drm_test_check_bpc_10_value
[04:02:16] [PASSED] drm_test_check_bpc_12_value
[04:02:16] [PASSED] drm_test_check_format_value
[04:02:16] [PASSED] drm_test_check_tmds_char_value
[04:02:16] ===== [PASSED] drm_atomic_helper_connector_hdmi_reset ======
[04:02:16] = drm_atomic_helper_connector_hdmi_mode_valid (4 subtests) =
[04:02:16] [PASSED] drm_test_check_mode_valid
[04:02:16] [PASSED] drm_test_check_mode_valid_reject
[04:02:16] [PASSED] drm_test_check_mode_valid_reject_rate
[04:02:16] [PASSED] drm_test_check_mode_valid_reject_max_clock
[04:02:16] === [PASSED] drm_atomic_helper_connector_hdmi_mode_valid ===
[04:02:16] ================= drm_managed (2 subtests) =================
[04:02:16] [PASSED] drm_test_managed_release_action
[04:02:16] [PASSED] drm_test_managed_run_action
[04:02:16] =================== [PASSED] drm_managed ===================
[04:02:16] =================== drm_mm (6 subtests) ====================
[04:02:16] [PASSED] drm_test_mm_init
[04:02:16] [PASSED] drm_test_mm_debug
[04:02:16] [PASSED] drm_test_mm_align32
[04:02:16] [PASSED] drm_test_mm_align64
[04:02:16] [PASSED] drm_test_mm_lowest
[04:02:16] [PASSED] drm_test_mm_highest
[04:02:16] ===================== [PASSED] drm_mm ======================
[04:02:16] ============= drm_modes_analog_tv (5 subtests) =============
[04:02:16] [PASSED] drm_test_modes_analog_tv_mono_576i
[04:02:16] [PASSED] drm_test_modes_analog_tv_ntsc_480i
[04:02:16] [PASSED] drm_test_modes_analog_tv_ntsc_480i_inlined
[04:02:16] [PASSED] drm_test_modes_analog_tv_pal_576i
[04:02:16] [PASSED] drm_test_modes_analog_tv_pal_576i_inlined
[04:02:16] =============== [PASSED] drm_modes_analog_tv ===============
[04:02:16] ============== drm_plane_helper (2 subtests) ===============
[04:02:16] =============== drm_test_check_plane_state  ================
[04:02:16] [PASSED] clipping_simple
[04:02:16] [PASSED] clipping_rotate_reflect
[04:02:16] [PASSED] positioning_simple
[04:02:16] [PASSED] upscaling
[04:02:16] [PASSED] downscaling
[04:02:16] [PASSED] rounding1
[04:02:16] [PASSED] rounding2
[04:02:16] [PASSED] rounding3
[04:02:16] [PASSED] rounding4
[04:02:16] =========== [PASSED] drm_test_check_plane_state ============
[04:02:16] =========== drm_test_check_invalid_plane_state  ============
[04:02:16] [PASSED] positioning_invalid
[04:02:16] [PASSED] upscaling_invalid
[04:02:16] [PASSED] downscaling_invalid
[04:02:16] ======= [PASSED] drm_test_check_invalid_plane_state ========
[04:02:16] ================ [PASSED] drm_plane_helper =================
[04:02:16] ====== drm_connector_helper_tv_get_modes (1 subtest) =======
[04:02:16] ====== drm_test_connector_helper_tv_get_modes_check  =======
[04:02:16] [PASSED] None
[04:02:16] [PASSED] PAL
[04:02:16] [PASSED] NTSC
[04:02:16] [PASSED] Both, NTSC Default
[04:02:16] [PASSED] Both, PAL Default
[04:02:16] [PASSED] Both, NTSC Default, with PAL on command-line
[04:02:16] [PASSED] Both, PAL Default, with NTSC on command-line
[04:02:16] == [PASSED] drm_test_connector_helper_tv_get_modes_check ===
[04:02:16] ======== [PASSED] drm_connector_helper_tv_get_modes ========
[04:02:16] ================== drm_rect (9 subtests) ===================
[04:02:16] [PASSED] drm_test_rect_clip_scaled_div_by_zero
[04:02:16] [PASSED] drm_test_rect_clip_scaled_not_clipped
[04:02:16] [PASSED] drm_test_rect_clip_scaled_clipped
[04:02:16] [PASSED] drm_test_rect_clip_scaled_signed_vs_unsigned
[04:02:16] ================= drm_test_rect_intersect  =================
[04:02:16] [PASSED] top-left x bottom-right: 2x2+1+1 x 2x2+0+0
[04:02:16] [PASSED] top-right x bottom-left: 2x2+0+0 x 2x2+1-1
[04:02:16] [PASSED] bottom-left x top-right: 2x2+1-1 x 2x2+0+0
[04:02:16] [PASSED] bottom-right x top-left: 2x2+0+0 x 2x2+1+1
[04:02:16] [PASSED] right x left: 2x1+0+0 x 3x1+1+0
[04:02:16] [PASSED] left x right: 3x1+1+0 x 2x1+0+0
[04:02:16] [PASSED] up x bottom: 1x2+0+0 x 1x3+0-1
[04:02:16] [PASSED] bottom x up: 1x3+0-1 x 1x2+0+0
[04:02:16] [PASSED] touching corner: 1x1+0+0 x 2x2+1+1
[04:02:16] [PASSED] touching side: 1x1+0+0 x 1x1+1+0
[04:02:16] [PASSED] equal rects: 2x2+0+0 x 2x2+0+0
[04:02:16] [PASSED] inside another: 2x2+0+0 x 1x1+1+1
[04:02:16] [PASSED] far away: 1x1+0+0 x 1x1+3+6
[04:02:16] [PASSED] points intersecting: 0x0+5+10 x 0x0+5+10
[04:02:16] [PASSED] points not intersecting: 0x0+0+0 x 0x0+5+10
[04:02:16] ============= [PASSED] drm_test_rect_intersect =============
[04:02:16] ================ drm_test_rect_calc_hscale  ================
[04:02:16] [PASSED] normal use
[04:02:16] [PASSED] out of max range
[04:02:16] [PASSED] out of min range
[04:02:16] [PASSED] zero dst
[04:02:16] [PASSED] negative src
[04:02:16] [PASSED] negative dst
[04:02:16] ============ [PASSED] drm_test_rect_calc_hscale ============
[04:02:16] ================ drm_test_rect_calc_vscale  ================
[04:02:16] [PASSED] normal use
stty: 'standard input': Inappropriate ioctl for device
[04:02:16] [PASSED] out of max range
[04:02:16] [PASSED] out of min range
[04:02:16] [PASSED] zero dst
[04:02:16] [PASSED] negative src
[04:02:16] [PASSED] negative dst
[04:02:16] ============ [PASSED] drm_test_rect_calc_vscale ============
[04:02:16] ================== drm_test_rect_rotate  ===================
[04:02:16] [PASSED] reflect-x
[04:02:16] [PASSED] reflect-y
[04:02:16] [PASSED] rotate-0
[04:02:16] [PASSED] rotate-90
[04:02:16] [PASSED] rotate-180
[04:02:16] [PASSED] rotate-270
[04:02:16] ============== [PASSED] drm_test_rect_rotate ===============
[04:02:16] ================ drm_test_rect_rotate_inv  =================
[04:02:16] [PASSED] reflect-x
[04:02:16] [PASSED] reflect-y
[04:02:16] [PASSED] rotate-0
[04:02:16] [PASSED] rotate-90
[04:02:16] [PASSED] rotate-180
[04:02:16] [PASSED] rotate-270
[04:02:16] ============ [PASSED] drm_test_rect_rotate_inv =============
[04:02:16] ==================== [PASSED] drm_rect =====================
[04:02:16] ============ drm_sysfb_modeset_test (1 subtest) ============
[04:02:16] ============ drm_test_sysfb_build_fourcc_list  =============
[04:02:16] [PASSED] no native formats
[04:02:16] [PASSED] XRGB8888 as native format
[04:02:16] [PASSED] remove duplicates
[04:02:16] [PASSED] convert alpha formats
[04:02:16] [PASSED] random formats
[04:02:16] ======== [PASSED] drm_test_sysfb_build_fourcc_list =========
[04:02:16] ============= [PASSED] drm_sysfb_modeset_test ==============
[04:02:16] ============================================================
[04:02:16] Testing complete. Ran 622 tests: passed: 622
[04:02:16] Elapsed time: 26.866s total, 1.760s configuring, 24.685s building, 0.394s running

+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/ttm/tests/.kunitconfig
[04:02:16] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[04:02:18] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[04:02:28] Starting KUnit Kernel (1/1)...
[04:02:28] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[04:02:28] ================= ttm_device (5 subtests) ==================
[04:02:28] [PASSED] ttm_device_init_basic
[04:02:28] [PASSED] ttm_device_init_multiple
[04:02:28] [PASSED] ttm_device_fini_basic
[04:02:28] [PASSED] ttm_device_init_no_vma_man
[04:02:28] ================== ttm_device_init_pools  ==================
[04:02:28] [PASSED] No DMA allocations, no DMA32 required
[04:02:28] [PASSED] DMA allocations, DMA32 required
[04:02:28] [PASSED] No DMA allocations, DMA32 required
[04:02:28] [PASSED] DMA allocations, no DMA32 required
[04:02:28] ============== [PASSED] ttm_device_init_pools ==============
[04:02:28] =================== [PASSED] ttm_device ====================
[04:02:28] ================== ttm_pool (8 subtests) ===================
[04:02:28] ================== ttm_pool_alloc_basic  ===================
[04:02:28] [PASSED] One page
[04:02:28] [PASSED] More than one page
[04:02:28] [PASSED] Above the allocation limit
[04:02:28] [PASSED] One page, with coherent DMA mappings enabled
[04:02:28] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[04:02:28] ============== [PASSED] ttm_pool_alloc_basic ===============
[04:02:28] ============== ttm_pool_alloc_basic_dma_addr  ==============
[04:02:28] [PASSED] One page
[04:02:28] [PASSED] More than one page
[04:02:28] [PASSED] Above the allocation limit
[04:02:28] [PASSED] One page, with coherent DMA mappings enabled
[04:02:28] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[04:02:28] ========== [PASSED] ttm_pool_alloc_basic_dma_addr ==========
[04:02:28] [PASSED] ttm_pool_alloc_order_caching_match
[04:02:28] [PASSED] ttm_pool_alloc_caching_mismatch
[04:02:28] [PASSED] ttm_pool_alloc_order_mismatch
[04:02:28] [PASSED] ttm_pool_free_dma_alloc
[04:02:28] [PASSED] ttm_pool_free_no_dma_alloc
[04:02:28] [PASSED] ttm_pool_fini_basic
[04:02:28] ==================== [PASSED] ttm_pool =====================
[04:02:28] ================ ttm_resource (8 subtests) =================
[04:02:28] ================= ttm_resource_init_basic  =================
[04:02:28] [PASSED] Init resource in TTM_PL_SYSTEM
[04:02:28] [PASSED] Init resource in TTM_PL_VRAM
[04:02:28] [PASSED] Init resource in a private placement
[04:02:28] [PASSED] Init resource in TTM_PL_SYSTEM, set placement flags
[04:02:28] ============= [PASSED] ttm_resource_init_basic =============
[04:02:28] [PASSED] ttm_resource_init_pinned
[04:02:28] [PASSED] ttm_resource_fini_basic
[04:02:28] [PASSED] ttm_resource_manager_init_basic
[04:02:28] [PASSED] ttm_resource_manager_usage_basic
[04:02:28] [PASSED] ttm_resource_manager_set_used_basic
[04:02:28] [PASSED] ttm_sys_man_alloc_basic
[04:02:28] [PASSED] ttm_sys_man_free_basic
[04:02:28] ================== [PASSED] ttm_resource ===================
[04:02:28] =================== ttm_tt (15 subtests) ===================
[04:02:28] ==================== ttm_tt_init_basic  ====================
[04:02:28] [PASSED] Page-aligned size
[04:02:28] [PASSED] Extra pages requested
[04:02:28] ================ [PASSED] ttm_tt_init_basic ================
[04:02:28] [PASSED] ttm_tt_init_misaligned
[04:02:28] [PASSED] ttm_tt_fini_basic
[04:02:28] [PASSED] ttm_tt_fini_sg
[04:02:28] [PASSED] ttm_tt_fini_shmem
[04:02:28] [PASSED] ttm_tt_create_basic
[04:02:28] [PASSED] ttm_tt_create_invalid_bo_type
[04:02:28] [PASSED] ttm_tt_create_ttm_exists
[04:02:28] [PASSED] ttm_tt_create_failed
[04:02:28] [PASSED] ttm_tt_destroy_basic
[04:02:28] [PASSED] ttm_tt_populate_null_ttm
[04:02:28] [PASSED] ttm_tt_populate_populated_ttm
[04:02:28] [PASSED] ttm_tt_unpopulate_basic
[04:02:28] [PASSED] ttm_tt_unpopulate_empty_ttm
[04:02:28] [PASSED] ttm_tt_swapin_basic
[04:02:28] ===================== [PASSED] ttm_tt ======================
[04:02:28] =================== ttm_bo (14 subtests) ===================
[04:02:28] =========== ttm_bo_reserve_optimistic_no_ticket  ===========
[04:02:28] [PASSED] Cannot be interrupted and sleeps
[04:02:28] [PASSED] Cannot be interrupted, locks straight away
[04:02:28] [PASSED] Can be interrupted, sleeps
[04:02:28] ======= [PASSED] ttm_bo_reserve_optimistic_no_ticket =======
[04:02:28] [PASSED] ttm_bo_reserve_locked_no_sleep
[04:02:28] [PASSED] ttm_bo_reserve_no_wait_ticket
[04:02:28] [PASSED] ttm_bo_reserve_double_resv
[04:02:28] [PASSED] ttm_bo_reserve_interrupted
[04:02:28] [PASSED] ttm_bo_reserve_deadlock
[04:02:28] [PASSED] ttm_bo_unreserve_basic
[04:02:28] [PASSED] ttm_bo_unreserve_pinned
[04:02:28] [PASSED] ttm_bo_unreserve_bulk
[04:02:28] [PASSED] ttm_bo_fini_basic
[04:02:28] [PASSED] ttm_bo_fini_shared_resv
[04:02:28] [PASSED] ttm_bo_pin_basic
[04:02:28] [PASSED] ttm_bo_pin_unpin_resource
[04:02:28] [PASSED] ttm_bo_multiple_pin_one_unpin
[04:02:28] ===================== [PASSED] ttm_bo ======================
[04:02:28] ============== ttm_bo_validate (21 subtests) ===============
[04:02:28] ============== ttm_bo_init_reserved_sys_man  ===============
[04:02:28] [PASSED] Buffer object for userspace
[04:02:28] [PASSED] Kernel buffer object
[04:02:28] [PASSED] Shared buffer object
[04:02:28] ========== [PASSED] ttm_bo_init_reserved_sys_man ===========
[04:02:28] ============== ttm_bo_init_reserved_mock_man  ==============
[04:02:28] [PASSED] Buffer object for userspace
[04:02:28] [PASSED] Kernel buffer object
[04:02:28] [PASSED] Shared buffer object
[04:02:28] ========== [PASSED] ttm_bo_init_reserved_mock_man ==========
[04:02:28] [PASSED] ttm_bo_init_reserved_resv
[04:02:28] ================== ttm_bo_validate_basic  ==================
[04:02:28] [PASSED] Buffer object for userspace
[04:02:28] [PASSED] Kernel buffer object
[04:02:28] [PASSED] Shared buffer object
[04:02:28] ============== [PASSED] ttm_bo_validate_basic ==============
[04:02:28] [PASSED] ttm_bo_validate_invalid_placement
[04:02:28] ============= ttm_bo_validate_same_placement  ==============
[04:02:28] [PASSED] System manager
[04:02:28] [PASSED] VRAM manager
[04:02:28] ========= [PASSED] ttm_bo_validate_same_placement ==========
[04:02:28] [PASSED] ttm_bo_validate_failed_alloc
[04:02:28] [PASSED] ttm_bo_validate_pinned
[04:02:28] [PASSED] ttm_bo_validate_busy_placement
[04:02:28] ================ ttm_bo_validate_multihop  =================
[04:02:28] [PASSED] Buffer object for userspace
[04:02:28] [PASSED] Kernel buffer object
[04:02:28] [PASSED] Shared buffer object
[04:02:28] ============ [PASSED] ttm_bo_validate_multihop =============
[04:02:28] ========== ttm_bo_validate_no_placement_signaled  ==========
[04:02:28] [PASSED] Buffer object in system domain, no page vector
[04:02:28] [PASSED] Buffer object in system domain with an existing page vector
[04:02:28] ====== [PASSED] ttm_bo_validate_no_placement_signaled ======
[04:02:28] ======== ttm_bo_validate_no_placement_not_signaled  ========
[04:02:28] [PASSED] Buffer object for userspace
[04:02:28] [PASSED] Kernel buffer object
[04:02:28] [PASSED] Shared buffer object
[04:02:28] ==== [PASSED] ttm_bo_validate_no_placement_not_signaled ====
[04:02:28] [PASSED] ttm_bo_validate_move_fence_signaled
[04:02:28] ========= ttm_bo_validate_move_fence_not_signaled  =========
[04:02:28] [PASSED] Waits for GPU
[04:02:28] [PASSED] Tries to lock straight away
[04:02:28] ===== [PASSED] ttm_bo_validate_move_fence_not_signaled =====
[04:02:28] [PASSED] ttm_bo_validate_happy_evict
[04:02:28] [PASSED] ttm_bo_validate_all_pinned_evict
[04:02:28] [PASSED] ttm_bo_validate_allowed_only_evict
[04:02:28] [PASSED] ttm_bo_validate_deleted_evict
[04:02:28] [PASSED] ttm_bo_validate_busy_domain_evict
[04:02:28] [PASSED] ttm_bo_validate_evict_gutting
[04:02:28] [PASSED] ttm_bo_validate_recrusive_evict
stty: 'standard input': Inappropriate ioctl for device
[04:02:28] ================= [PASSED] ttm_bo_validate =================
[04:02:28] ============================================================
[04:02:28] Testing complete. Ran 101 tests: passed: 101
[04:02:28] Elapsed time: 11.374s total, 1.744s configuring, 9.415s building, 0.186s running

+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel



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

* ✗ Xe.CI.BAT: failure for drm/xe: Multi Queue feature support (rev3)
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (19 preceding siblings ...)
  2025-11-21  4:02 ` ✓ CI.KUnit: success " Patchwork
@ 2025-11-21  4:51 ` Patchwork
  2025-11-21  8:10 ` ✗ Xe.CI.Full: " Patchwork
                   ` (2 subsequent siblings)
  23 siblings, 0 replies; 41+ messages in thread
From: Patchwork @ 2025-11-21  4:51 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

[-- Attachment #1: Type: text/plain, Size: 6286 bytes --]

== Series Details ==

Series: drm/xe: Multi Queue feature support (rev3)
URL   : https://patchwork.freedesktop.org/series/156865/
State : failure

== Summary ==

CI Bug Log - changes from xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7_BAT -> xe-pw-156865v3_BAT
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with xe-pw-156865v3_BAT absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in xe-pw-156865v3_BAT, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Participating hosts (13 -> 13)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in xe-pw-156865v3_BAT:

### IGT changes ###

#### Possible regressions ####

  * igt@xe_exec_queue_property@invalid-property:
    - bat-ptl-2:          [PASS][1] -> [FAIL][2]
   [1]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/bat-ptl-2/igt@xe_exec_queue_property@invalid-property.html
   [2]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/bat-ptl-2/igt@xe_exec_queue_property@invalid-property.html
    - bat-dg2-oem2:       [PASS][3] -> [FAIL][4]
   [3]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/bat-dg2-oem2/igt@xe_exec_queue_property@invalid-property.html
   [4]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/bat-dg2-oem2/igt@xe_exec_queue_property@invalid-property.html
    - bat-atsm-2:         [PASS][5] -> [FAIL][6]
   [5]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/bat-atsm-2/igt@xe_exec_queue_property@invalid-property.html
   [6]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/bat-atsm-2/igt@xe_exec_queue_property@invalid-property.html
    - bat-adlp-vm:        [PASS][7] -> [FAIL][8]
   [7]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/bat-adlp-vm/igt@xe_exec_queue_property@invalid-property.html
   [8]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/bat-adlp-vm/igt@xe_exec_queue_property@invalid-property.html
    - bat-ptl-1:          [PASS][9] -> [FAIL][10]
   [9]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/bat-ptl-1/igt@xe_exec_queue_property@invalid-property.html
   [10]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/bat-ptl-1/igt@xe_exec_queue_property@invalid-property.html
    - bat-lnl-1:          [PASS][11] -> [FAIL][12]
   [11]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/bat-lnl-1/igt@xe_exec_queue_property@invalid-property.html
   [12]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/bat-lnl-1/igt@xe_exec_queue_property@invalid-property.html
    - bat-pvc-2:          [PASS][13] -> [FAIL][14]
   [13]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/bat-pvc-2/igt@xe_exec_queue_property@invalid-property.html
   [14]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/bat-pvc-2/igt@xe_exec_queue_property@invalid-property.html
    - bat-ptl-vm:         [PASS][15] -> [FAIL][16]
   [15]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/bat-ptl-vm/igt@xe_exec_queue_property@invalid-property.html
   [16]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/bat-ptl-vm/igt@xe_exec_queue_property@invalid-property.html
    - bat-adlp-7:         [PASS][17] -> [FAIL][18]
   [17]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/bat-adlp-7/igt@xe_exec_queue_property@invalid-property.html
   [18]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/bat-adlp-7/igt@xe_exec_queue_property@invalid-property.html
    - bat-lnl-2:          [PASS][19] -> [FAIL][20]
   [19]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/bat-lnl-2/igt@xe_exec_queue_property@invalid-property.html
   [20]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/bat-lnl-2/igt@xe_exec_queue_property@invalid-property.html

  
Known issues
------------

  Here are the changes found in xe-pw-156865v3_BAT that come from known issues:

### IGT changes ###

#### Possible fixes ####

  * igt@xe_waitfence@abstime:
    - bat-dg2-oem2:       [TIMEOUT][21] ([Intel XE#6506]) -> [PASS][22]
   [21]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/bat-dg2-oem2/igt@xe_waitfence@abstime.html
   [22]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/bat-dg2-oem2/igt@xe_waitfence@abstime.html

  * igt@xe_waitfence@engine:
    - bat-dg2-oem2:       [FAIL][23] ([Intel XE#6519]) -> [PASS][24]
   [23]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/bat-dg2-oem2/igt@xe_waitfence@engine.html
   [24]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/bat-dg2-oem2/igt@xe_waitfence@engine.html

  * igt@xe_waitfence@reltime:
    - bat-dg2-oem2:       [FAIL][25] ([Intel XE#6520]) -> [PASS][26]
   [25]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/bat-dg2-oem2/igt@xe_waitfence@reltime.html
   [26]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/bat-dg2-oem2/igt@xe_waitfence@reltime.html

  
  [Intel XE#6506]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6506
  [Intel XE#6519]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6519
  [Intel XE#6520]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6520


Build changes
-------------

  * Linux: xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7 -> xe-pw-156865v3

  IGT_8636: 254cd102396ff95d61f2ebe49fc09128878bf483 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7: 3d718db04a365cc44a3bc81ffa4db7bbd2e645d7
  xe-pw-156865v3: 156865v3

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/index.html

[-- Attachment #2: Type: text/html, Size: 6989 bytes --]

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

* ✗ Xe.CI.Full: failure for drm/xe: Multi Queue feature support (rev3)
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (20 preceding siblings ...)
  2025-11-21  4:51 ` ✗ Xe.CI.BAT: failure " Patchwork
@ 2025-11-21  8:10 ` Patchwork
  2025-11-24 14:04 ` Patchwork
  2025-11-27  9:38 ` [PATCH v3 00/18] drm/xe: Multi Queue feature support Hoppe, Mateusz
  23 siblings, 0 replies; 41+ messages in thread
From: Patchwork @ 2025-11-21  8:10 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

[-- Attachment #1: Type: text/plain, Size: 19877 bytes --]

== Series Details ==

Series: drm/xe: Multi Queue feature support (rev3)
URL   : https://patchwork.freedesktop.org/series/156865/
State : failure

== Summary ==

CI Bug Log - changes from xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7_FULL -> xe-pw-156865v3_FULL
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with xe-pw-156865v3_FULL absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in xe-pw-156865v3_FULL, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Participating hosts (4 -> 4)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in xe-pw-156865v3_FULL:

### IGT changes ###

#### Possible regressions ####

  * igt@xe_exec_queue_property@invalid-property:
    - shard-dg2-set2:     [PASS][1] -> [FAIL][2]
   [1]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-dg2-466/igt@xe_exec_queue_property@invalid-property.html
   [2]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-466/igt@xe_exec_queue_property@invalid-property.html
    - shard-lnl:          [PASS][3] -> [FAIL][4]
   [3]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-lnl-3/igt@xe_exec_queue_property@invalid-property.html
   [4]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-lnl-3/igt@xe_exec_queue_property@invalid-property.html
    - shard-adlp:         [PASS][5] -> [FAIL][6]
   [5]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-adlp-4/igt@xe_exec_queue_property@invalid-property.html
   [6]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-3/igt@xe_exec_queue_property@invalid-property.html

  
New tests
---------

  New tests have been introduced between xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7_FULL and xe-pw-156865v3_FULL:

### New IGT tests (1) ###

  * igt@kms_dirtyfb@default-dirtyfb-ioctl@a-hdmi-a-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.29] s

  

Known issues
------------

  Here are the changes found in xe-pw-156865v3_FULL that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@kms_big_fb@x-tiled-32bpp-rotate-270:
    - shard-dg2-set2:     NOTRUN -> [SKIP][7] ([Intel XE#316])
   [7]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_big_fb@x-tiled-32bpp-rotate-270.html

  * igt@kms_big_fb@yf-tiled-32bpp-rotate-90:
    - shard-dg2-set2:     NOTRUN -> [SKIP][8] ([Intel XE#1124])
   [8]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_big_fb@yf-tiled-32bpp-rotate-90.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180:
    - shard-adlp:         NOTRUN -> [SKIP][9] ([Intel XE#1124])
   [9]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180.html

  * igt@kms_bw@connected-linear-tiling-3-displays-2560x1440p:
    - shard-adlp:         NOTRUN -> [SKIP][10] ([Intel XE#2191])
   [10]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_bw@connected-linear-tiling-3-displays-2560x1440p.html

  * igt@kms_bw@linear-tiling-3-displays-1920x1080p:
    - shard-dg2-set2:     NOTRUN -> [SKIP][11] ([Intel XE#367])
   [11]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_bw@linear-tiling-3-displays-1920x1080p.html

  * igt@kms_bw@linear-tiling-4-displays-3840x2160p:
    - shard-adlp:         NOTRUN -> [SKIP][12] ([Intel XE#367])
   [12]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_bw@linear-tiling-4-displays-3840x2160p.html

  * igt@kms_ccs@bad-aux-stride-4-tiled-mtl-rc-ccs-cc:
    - shard-dg2-set2:     NOTRUN -> [SKIP][13] ([Intel XE#455] / [Intel XE#787]) +1 other test skip
   [13]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_ccs@bad-aux-stride-4-tiled-mtl-rc-ccs-cc.html

  * igt@kms_ccs@bad-aux-stride-4-tiled-mtl-rc-ccs-cc@pipe-c-dp-4:
    - shard-dg2-set2:     NOTRUN -> [SKIP][14] ([Intel XE#787]) +6 other tests skip
   [14]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_ccs@bad-aux-stride-4-tiled-mtl-rc-ccs-cc@pipe-c-dp-4.html

  * igt@kms_ccs@crc-primary-basic-4-tiled-mtl-rc-ccs:
    - shard-adlp:         NOTRUN -> [SKIP][15] ([Intel XE#455] / [Intel XE#787]) +1 other test skip
   [15]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_ccs@crc-primary-basic-4-tiled-mtl-rc-ccs.html

  * igt@kms_ccs@crc-primary-basic-4-tiled-mtl-rc-ccs@pipe-c-hdmi-a-1:
    - shard-adlp:         NOTRUN -> [SKIP][16] ([Intel XE#787]) +2 other tests skip
   [16]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_ccs@crc-primary-basic-4-tiled-mtl-rc-ccs@pipe-c-hdmi-a-1.html

  * igt@kms_ccs@crc-sprite-planes-basic-4-tiled-bmg-ccs:
    - shard-adlp:         NOTRUN -> [SKIP][17] ([Intel XE#2907])
   [17]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_ccs@crc-sprite-planes-basic-4-tiled-bmg-ccs.html

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs@pipe-b-hdmi-a-6:
    - shard-dg2-set2:     [PASS][18] -> [INCOMPLETE][19] ([Intel XE#1727] / [Intel XE#3113] / [Intel XE#4345] / [Intel XE#6168])
   [18]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-dg2-464/igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs@pipe-b-hdmi-a-6.html
   [19]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-435/igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs@pipe-b-hdmi-a-6.html

  * igt@kms_chamelium_edid@dp-edid-change-during-hibernate:
    - shard-dg2-set2:     NOTRUN -> [SKIP][20] ([Intel XE#373])
   [20]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_chamelium_edid@dp-edid-change-during-hibernate.html

  * igt@kms_color@ctm-blue-to-red:
    - shard-adlp:         NOTRUN -> [DMESG-WARN][21] ([Intel XE#2953] / [Intel XE#4173]) +1 other test dmesg-warn
   [21]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_color@ctm-blue-to-red.html

  * igt@kms_cursor_crc@cursor-random-32x10:
    - shard-dg2-set2:     NOTRUN -> [SKIP][22] ([Intel XE#455])
   [22]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_cursor_crc@cursor-random-32x10.html

  * igt@kms_cursor_legacy@2x-nonblocking-modeset-vs-cursor-atomic:
    - shard-adlp:         NOTRUN -> [SKIP][23] ([Intel XE#309])
   [23]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_cursor_legacy@2x-nonblocking-modeset-vs-cursor-atomic.html

  * igt@kms_flip@flip-vs-suspend@b-hdmi-a1:
    - shard-adlp:         [PASS][24] -> [DMESG-WARN][25] ([Intel XE#2953] / [Intel XE#4173]) +2 other tests dmesg-warn
   [24]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-adlp-9/igt@kms_flip@flip-vs-suspend@b-hdmi-a1.html
   [25]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_flip@flip-vs-suspend@b-hdmi-a1.html

  * igt@kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-render:
    - shard-dg2-set2:     NOTRUN -> [SKIP][26] ([Intel XE#651])
   [26]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-indfb-pgflip-blt:
    - shard-adlp:         NOTRUN -> [SKIP][27] ([Intel XE#656])
   [27]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-indfb-pgflip-blt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-blt:
    - shard-dg2-set2:     NOTRUN -> [SKIP][28] ([Intel XE#653]) +1 other test skip
   [28]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-blt.html

  * igt@kms_pm_rpm@dpms-non-lpsp:
    - shard-adlp:         NOTRUN -> [SKIP][29] ([Intel XE#836])
   [29]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_pm_rpm@dpms-non-lpsp.html

  * igt@kms_psr2_sf@fbc-psr2-overlay-plane-update-sf-dmg-area:
    - shard-dg2-set2:     NOTRUN -> [SKIP][30] ([Intel XE#1406] / [Intel XE#1489])
   [30]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_psr2_sf@fbc-psr2-overlay-plane-update-sf-dmg-area.html

  * igt@kms_psr@fbc-psr2-primary-blt:
    - shard-dg2-set2:     NOTRUN -> [SKIP][31] ([Intel XE#1406] / [Intel XE#2850] / [Intel XE#929])
   [31]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_psr@fbc-psr2-primary-blt.html

  * igt@xe_eudebug@vm-bind-clear-faultable:
    - shard-dg2-set2:     NOTRUN -> [SKIP][32] ([Intel XE#4837]) +1 other test skip
   [32]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_eudebug@vm-bind-clear-faultable.html

  * igt@xe_exec_basic@multigpu-many-execqueues-many-vm-rebind:
    - shard-adlp:         NOTRUN -> [SKIP][33] ([Intel XE#1392] / [Intel XE#5575])
   [33]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@xe_exec_basic@multigpu-many-execqueues-many-vm-rebind.html

  * igt@xe_exec_fault_mode@once-userptr-prefetch:
    - shard-adlp:         NOTRUN -> [SKIP][34] ([Intel XE#288] / [Intel XE#5561]) +1 other test skip
   [34]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@xe_exec_fault_mode@once-userptr-prefetch.html

  * igt@xe_exec_fault_mode@twice-bindexecqueue-userptr-rebind-prefetch:
    - shard-dg2-set2:     NOTRUN -> [SKIP][35] ([Intel XE#288]) +2 other tests skip
   [35]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_exec_fault_mode@twice-bindexecqueue-userptr-rebind-prefetch.html

  * igt@xe_exec_system_allocator@process-many-large-execqueues-mmap-free:
    - shard-dg2-set2:     NOTRUN -> [SKIP][36] ([Intel XE#4915]) +36 other tests skip
   [36]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_exec_system_allocator@process-many-large-execqueues-mmap-free.html

  * igt@xe_exec_system_allocator@process-many-large-new-bo-map-nomemset:
    - shard-adlp:         NOTRUN -> [SKIP][37] ([Intel XE#4915]) +10 other tests skip
   [37]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@xe_exec_system_allocator@process-many-large-new-bo-map-nomemset.html

  * igt@xe_oa@create-destroy-userspace-config:
    - shard-dg2-set2:     NOTRUN -> [SKIP][38] ([Intel XE#3573]) +1 other test skip
   [38]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_oa@create-destroy-userspace-config.html

  * igt@xe_pm@s2idle-d3cold-basic-exec:
    - shard-dg2-set2:     NOTRUN -> [SKIP][39] ([Intel XE#2284] / [Intel XE#366])
   [39]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_pm@s2idle-d3cold-basic-exec.html

  * igt@xe_pmu@engine-activity-accuracy-90@engine-drm_xe_engine_class_copy0:
    - shard-lnl:          [PASS][40] -> [FAIL][41] ([Intel XE#6251]) +1 other test fail
   [40]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-lnl-1/igt@xe_pmu@engine-activity-accuracy-90@engine-drm_xe_engine_class_copy0.html
   [41]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-lnl-4/igt@xe_pmu@engine-activity-accuracy-90@engine-drm_xe_engine_class_copy0.html

  * igt@xe_pxp@pxp-stale-queue-post-suspend:
    - shard-dg2-set2:     NOTRUN -> [SKIP][42] ([Intel XE#4733])
   [42]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_pxp@pxp-stale-queue-post-suspend.html

  * igt@xe_query@multigpu-query-oa-units:
    - shard-dg2-set2:     NOTRUN -> [SKIP][43] ([Intel XE#944])
   [43]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_query@multigpu-query-oa-units.html

  
#### Possible fixes ####

  * igt@kms_async_flips@async-flip-with-page-flip-events-linear-atomic@pipe-c-edp-1:
    - shard-lnl:          [FAIL][44] ([Intel XE#6054]) -> [PASS][45] +3 other tests pass
   [44]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-lnl-4/igt@kms_async_flips@async-flip-with-page-flip-events-linear-atomic@pipe-c-edp-1.html
   [45]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-lnl-5/igt@kms_async_flips@async-flip-with-page-flip-events-linear-atomic@pipe-c-edp-1.html

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc:
    - shard-dg2-set2:     [INCOMPLETE][46] ([Intel XE#2705] / [Intel XE#4212] / [Intel XE#4345]) -> [PASS][47]
   [46]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-dg2-436/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc.html
   [47]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc.html

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc@pipe-b-dp-4:
    - shard-dg2-set2:     [INCOMPLETE][48] ([Intel XE#2705] / [Intel XE#4212]) -> [PASS][49]
   [48]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-dg2-436/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc@pipe-b-dp-4.html
   [49]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc@pipe-b-dp-4.html

  * igt@kms_cursor_edge_walk@256x256-top-bottom:
    - shard-adlp:         [DMESG-WARN][50] ([Intel XE#2953] / [Intel XE#4173]) -> [PASS][51] +6 other tests pass
   [50]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-adlp-3/igt@kms_cursor_edge_walk@256x256-top-bottom.html
   [51]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-9/igt@kms_cursor_edge_walk@256x256-top-bottom.html

  * igt@xe_oa@non-zero-reason-all:
    - shard-lnl:          [FAIL][52] ([Intel XE#6332]) -> [PASS][53] +1 other test pass
   [52]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-lnl-3/igt@xe_oa@non-zero-reason-all.html
   [53]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-lnl-4/igt@xe_oa@non-zero-reason-all.html

  
#### Warnings ####

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs:
    - shard-dg2-set2:     [INCOMPLETE][54] ([Intel XE#2705] / [Intel XE#4212] / [Intel XE#4345]) -> [INCOMPLETE][55] ([Intel XE#1727] / [Intel XE#3113] / [Intel XE#4345] / [Intel XE#6168])
   [54]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-dg2-464/igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs.html
   [55]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-435/igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs.html

  * igt@xe_exec_basic@multigpu-once-null-defer-bind:
    - shard-dg2-set2:     [INCOMPLETE][56] -> [INCOMPLETE][57] ([Intel XE#4842])
   [56]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-dg2-463/igt@xe_exec_basic@multigpu-once-null-defer-bind.html
   [57]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-436/igt@xe_exec_basic@multigpu-once-null-defer-bind.html

  * igt@xe_sriov_scheduling@equal-throughput:
    - shard-adlp:         [DMESG-FAIL][58] ([Intel XE#3868] / [Intel XE#5213]) -> [DMESG-FAIL][59] ([Intel XE#3868] / [Intel XE#5213] / [Intel XE#5545]) +1 other test dmesg-fail
   [58]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-adlp-6/igt@xe_sriov_scheduling@equal-throughput.html
   [59]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-3/igt@xe_sriov_scheduling@equal-throughput.html

  
  [Intel XE#1124]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1124
  [Intel XE#1392]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1392
  [Intel XE#1406]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1406
  [Intel XE#1489]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1489
  [Intel XE#1727]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1727
  [Intel XE#2191]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2191
  [Intel XE#2284]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2284
  [Intel XE#2705]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2705
  [Intel XE#2850]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2850
  [Intel XE#288]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/288
  [Intel XE#2907]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2907
  [Intel XE#2953]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2953
  [Intel XE#309]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/309
  [Intel XE#3113]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3113
  [Intel XE#316]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/316
  [Intel XE#3573]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3573
  [Intel XE#366]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/366
  [Intel XE#367]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/367
  [Intel XE#373]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/373
  [Intel XE#3868]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3868
  [Intel XE#4173]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4173
  [Intel XE#4212]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4212
  [Intel XE#4345]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4345
  [Intel XE#455]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/455
  [Intel XE#4733]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4733
  [Intel XE#4837]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4837
  [Intel XE#4842]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4842
  [Intel XE#4915]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4915
  [Intel XE#5213]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5213
  [Intel XE#5545]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5545
  [Intel XE#5561]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5561
  [Intel XE#5575]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5575
  [Intel XE#6054]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6054
  [Intel XE#6168]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6168
  [Intel XE#6251]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6251
  [Intel XE#6332]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6332
  [Intel XE#651]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/651
  [Intel XE#653]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/653
  [Intel XE#656]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/656
  [Intel XE#787]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/787
  [Intel XE#836]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/836
  [Intel XE#929]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/929
  [Intel XE#944]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/944


Build changes
-------------

  * Linux: xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7 -> xe-pw-156865v3

  IGT_8636: 254cd102396ff95d61f2ebe49fc09128878bf483 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7: 3d718db04a365cc44a3bc81ffa4db7bbd2e645d7
  xe-pw-156865v3: 156865v3

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/index.html

[-- Attachment #2: Type: text/html, Size: 23238 bytes --]

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

* Re: [PATCH v3 02/18] drm/xe/multi_queue: Add user interface for multi queue support
  2025-11-21  3:51 ` [PATCH v3 02/18] drm/xe/multi_queue: Add user interface for multi queue support Niranjana Vishwanathapura
@ 2025-11-21 22:51   ` Matthew Brost
  2025-11-22  4:35     ` Niranjana Vishwanathapura
  0 siblings, 1 reply; 41+ messages in thread
From: Matthew Brost @ 2025-11-21 22:51 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

On Thu, Nov 20, 2025 at 07:51:36PM -0800, Niranjana Vishwanathapura wrote:
> Multi Queue is a new mode of execution supported by the compute and
> blitter copy command streamers (CCS and BCS, respectively). It is an
> enhancement of the existing hardware architecture and leverages the
> same submission model. It enables support for efficient, parallel
> execution of multiple queues within a single context. All the queues
> of a group must use the same address space (VM).
> 
> The new DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE execution queue
> property supports creating a multi queue group and adding queues to
> a queue group. All queues of a multi queue group share the same
> context.
> 
> A exec queue create ioctl call with above property specified with value
> DRM_XE_SUPER_GROUP_CREATE will create a new multi queue group with the
> queue being created as the primary queue (aka q0) of the group. To add
> secondary queues to the group, they need to be created with the above
> property with id of the primary queue as the value. The properties of
> the primary queue (like priority, timeslice) applies to the whole group.
> So, these properties can't be set for secondary queues of a group.
> 
> Once destroyed, the secondary queues of a multi queue group can't be
> replaced. However, they can be dynamically added to the group up to a
> total of 64 queues per group. Once the primary queue is destroyed,
> secondary queues can't be added to the queue group.
> 
> v2: Remove group->lock, fix xe_exec_queue_group_add()/delete()
>     function semantics, add additional comments, remove unused
>     group->list_lock, add XE_BO_FLAG_GGTT_INVALIDATE for cgp bo,
>     Assert LRC is valid, update uapi kernel doc.
>     (Matt Brost)
> v3: Use XE_BO_FLAG_PINNED_LATE_RESTORE/USER_VRAM/GGTT_INVALIDATE
>     flags for cgp bo (Matt)
> 
> Signed-off-by: Stuart Summers <stuart.summers@intel.com>
> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

As this is new uAPI we will need a UMD PR and ack from a UMD team.

Matt

> ---
>  drivers/gpu/drm/xe/xe_exec_queue.c       | 194 ++++++++++++++++++++++-
>  drivers/gpu/drm/xe/xe_exec_queue.h       |  47 ++++++
>  drivers/gpu/drm/xe/xe_exec_queue_types.h |  26 +++
>  include/uapi/drm/xe_drm.h                |  10 ++
>  4 files changed, 275 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
> index 8724f8de67e2..330b5103222c 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue.c
> +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
> @@ -13,6 +13,7 @@
>  #include <drm/drm_syncobj.h>
>  #include <uapi/drm/xe_drm.h>
>  
> +#include "xe_bo.h"
>  #include "xe_dep_scheduler.h"
>  #include "xe_device.h"
>  #include "xe_gt.h"
> @@ -63,6 +64,33 @@ enum xe_exec_queue_sched_prop {
>  static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue *q,
>  				      u64 extensions, int ext_number);
>  
> +static void xe_exec_queue_group_cleanup(struct xe_exec_queue *q)
> +{
> +	struct xe_exec_queue_group *group = q->multi_queue.group;
> +	struct xe_lrc *lrc;
> +	unsigned long idx;
> +
> +	if (xe_exec_queue_is_multi_queue_secondary(q)) {
> +		/*
> +		 * Put pairs with get from xe_exec_queue_lookup() call
> +		 * in xe_exec_queue_group_validate().
> +		 */
> +		xe_exec_queue_put(xe_exec_queue_multi_queue_primary(q));
> +		return;
> +	}
> +
> +	if (!group)
> +		return;
> +
> +	/* Primary queue cleanup */
> +	xa_for_each(&group->xa, idx, lrc)
> +		xe_lrc_put(lrc);
> +
> +	xa_destroy(&group->xa);
> +	xe_bo_unpin_map_no_vm(group->cgp_bo);
> +	kfree(group);
> +}
> +
>  static void __xe_exec_queue_free(struct xe_exec_queue *q)
>  {
>  	int i;
> @@ -73,6 +101,10 @@ static void __xe_exec_queue_free(struct xe_exec_queue *q)
>  
>  	if (xe_exec_queue_uses_pxp(q))
>  		xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q);
> +
> +	if (xe_exec_queue_is_multi_queue(q))
> +		xe_exec_queue_group_cleanup(q);
> +
>  	if (q->vm)
>  		xe_vm_put(q->vm);
>  
> @@ -567,6 +599,147 @@ exec_queue_set_pxp_type(struct xe_device *xe, struct xe_exec_queue *q, u64 value
>  	return xe_pxp_exec_queue_set_type(xe->pxp, q, DRM_XE_PXP_TYPE_HWDRM);
>  }
>  
> +static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue *q)
> +{
> +	struct xe_tile *tile = gt_to_tile(q->gt);
> +	struct xe_exec_queue_group *group;
> +	struct xe_bo *bo;
> +
> +	group = kzalloc(sizeof(*group), GFP_KERNEL);
> +	if (!group)
> +		return -ENOMEM;
> +
> +	bo = xe_bo_create_pin_map_novm(xe, tile, SZ_4K, ttm_bo_type_kernel,
> +				       XE_BO_FLAG_VRAM_IF_DGFX(tile) |
> +				       XE_BO_FLAG_PINNED_LATE_RESTORE |
> +				       XE_BO_FLAG_FORCE_USER_VRAM |
> +				       XE_BO_FLAG_GGTT_INVALIDATE |
> +				       XE_BO_FLAG_GGTT, false);
> +	if (IS_ERR(bo)) {
> +		drm_err(&xe->drm, "CGP bo allocation for queue group failed: %ld\n",
> +			PTR_ERR(bo));
> +		kfree(group);
> +		return PTR_ERR(bo);
> +	}
> +
> +	xe_map_memset(xe, &bo->vmap, 0, 0, SZ_4K);
> +
> +	group->primary = q;
> +	group->cgp_bo = bo;
> +	xa_init_flags(&group->xa, XA_FLAGS_ALLOC1);
> +	q->multi_queue.group = group;
> +
> +	return 0;
> +}
> +
> +static inline bool xe_exec_queue_supports_multi_queue(struct xe_exec_queue *q)
> +{
> +	return q->gt->info.multi_queue_engine_class_mask & BIT(q->class);
> +}
> +
> +static int xe_exec_queue_group_validate(struct xe_device *xe, struct xe_exec_queue *q,
> +					u32 primary_id)
> +{
> +	struct xe_exec_queue_group *group;
> +	struct xe_exec_queue *primary;
> +	int ret;
> +
> +	/*
> +	 * Get from below xe_exec_queue_lookup() pairs with put
> +	 * in xe_exec_queue_group_cleanup().
> +	 */
> +	primary = xe_exec_queue_lookup(q->vm->xef, primary_id);
> +	if (XE_IOCTL_DBG(xe, !primary))
> +		return -ENOENT;
> +
> +	if (XE_IOCTL_DBG(xe, !xe_exec_queue_is_multi_queue_primary(primary)) ||
> +	    XE_IOCTL_DBG(xe, q->vm != primary->vm) ||
> +	    XE_IOCTL_DBG(xe, q->logical_mask != primary->logical_mask)) {
> +		ret = -EINVAL;
> +		goto put_primary;
> +	}
> +
> +	group = primary->multi_queue.group;
> +	q->multi_queue.valid = true;
> +	q->multi_queue.group = group;
> +
> +	return 0;
> +put_primary:
> +	xe_exec_queue_put(primary);
> +	return ret;
> +}
> +
> +#define XE_MAX_GROUP_SIZE	64
> +static int xe_exec_queue_group_add(struct xe_device *xe, struct xe_exec_queue *q)
> +{
> +	struct xe_exec_queue_group *group = q->multi_queue.group;
> +	u32 pos;
> +	int err;
> +
> +	xe_assert(xe, xe_exec_queue_is_multi_queue_secondary(q));
> +
> +	/* Primary queue holds a reference to LRCs of all secondary queues */
> +	err = xa_alloc(&group->xa, &pos, xe_lrc_get(q->lrc[0]),
> +		       XA_LIMIT(1, XE_MAX_GROUP_SIZE - 1), GFP_KERNEL);
> +	if (XE_IOCTL_DBG(xe, err)) {
> +		xe_lrc_put(q->lrc[0]);
> +
> +		/* It is invalid if queue group limit is exceeded */
> +		if (err == -EBUSY)
> +			err = -EINVAL;
> +
> +		return err;
> +	}
> +
> +	q->multi_queue.pos = pos;
> +
> +	return 0;
> +}
> +
> +static void xe_exec_queue_group_delete(struct xe_device *xe, struct xe_exec_queue *q)
> +{
> +	struct xe_exec_queue_group *group = q->multi_queue.group;
> +	struct xe_lrc *lrc;
> +
> +	xe_assert(xe, xe_exec_queue_is_multi_queue_secondary(q));
> +
> +	lrc = xa_erase(&group->xa, q->multi_queue.pos);
> +	xe_assert(xe, lrc);
> +	xe_lrc_put(lrc);
> +}
> +
> +static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue *q,
> +				      u64 value)
> +{
> +	if (XE_IOCTL_DBG(xe, !xe_exec_queue_supports_multi_queue(q)))
> +		return -ENODEV;
> +
> +	if (XE_IOCTL_DBG(xe, !xe_device_uc_enabled(xe)))
> +		return -EOPNOTSUPP;
> +
> +	if (XE_IOCTL_DBG(xe, xe_exec_queue_is_parallel(q)))
> +		return -EINVAL;
> +
> +	if (XE_IOCTL_DBG(xe, xe_exec_queue_is_multi_queue(q)))
> +		return -EINVAL;
> +
> +	if (value & DRM_XE_MULTI_GROUP_CREATE) {
> +		if (XE_IOCTL_DBG(xe, value & ~DRM_XE_MULTI_GROUP_CREATE))
> +			return -EINVAL;
> +
> +		q->multi_queue.valid = true;
> +		q->multi_queue.is_primary = true;
> +		q->multi_queue.pos = 0;
> +		return 0;
> +	}
> +
> +	/* While adding secondary queues, the upper 32 bits must be 0 */
> +	if (XE_IOCTL_DBG(xe, value & (~0ull << 32)))
> +		return -EINVAL;
> +
> +	return xe_exec_queue_group_validate(xe, q, value);
> +}
> +
>  typedef int (*xe_exec_queue_set_property_fn)(struct xe_device *xe,
>  					     struct xe_exec_queue *q,
>  					     u64 value);
> @@ -575,6 +748,7 @@ static const xe_exec_queue_set_property_fn exec_queue_set_property_funcs[] = {
>  	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY] = exec_queue_set_priority,
>  	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE] = exec_queue_set_timeslice,
>  	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE] = exec_queue_set_pxp_type,
> +	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP] = exec_queue_set_multi_group,
>  };
>  
>  static int exec_queue_user_ext_set_property(struct xe_device *xe,
> @@ -595,7 +769,8 @@ static int exec_queue_user_ext_set_property(struct xe_device *xe,
>  	    XE_IOCTL_DBG(xe, ext.pad) ||
>  	    XE_IOCTL_DBG(xe, ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY &&
>  			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE &&
> -			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE))
> +			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE &&
> +			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP))
>  		return -EINVAL;
>  
>  	idx = array_index_nospec(ext.property, ARRAY_SIZE(exec_queue_set_property_funcs));
> @@ -644,6 +819,12 @@ static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue
>  		return exec_queue_user_extensions(xe, q, ext.next_extension,
>  						  ++ext_number);
>  
> +	if (xe_exec_queue_is_multi_queue_primary(q)) {
> +		err = xe_exec_queue_group_init(xe, q);
> +		if (XE_IOCTL_DBG(xe, err))
> +			return err;
> +	}
> +
>  	return 0;
>  }
>  
> @@ -798,12 +979,18 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
>  		if (IS_ERR(q))
>  			return PTR_ERR(q);
>  
> +		if (xe_exec_queue_is_multi_queue_secondary(q)) {
> +			err = xe_exec_queue_group_add(xe, q);
> +			if (XE_IOCTL_DBG(xe, err))
> +				goto put_exec_queue;
> +		}
> +
>  		if (xe_vm_in_preempt_fence_mode(vm)) {
>  			q->lr.context = dma_fence_context_alloc(1);
>  
>  			err = xe_vm_add_compute_exec_queue(vm, q);
>  			if (XE_IOCTL_DBG(xe, err))
> -				goto put_exec_queue;
> +				goto delete_queue_group;
>  		}
>  
>  		if (q->vm && q->hwe->hw_engine_group) {
> @@ -826,6 +1013,9 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
>  
>  kill_exec_queue:
>  	xe_exec_queue_kill(q);
> +delete_queue_group:
> +	if (xe_exec_queue_is_multi_queue_secondary(q))
> +		xe_exec_queue_group_delete(xe, q);
>  put_exec_queue:
>  	xe_exec_queue_put(q);
>  	return err;
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.h b/drivers/gpu/drm/xe/xe_exec_queue.h
> index fda4d4f9bda8..e6daa40003f2 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue.h
> +++ b/drivers/gpu/drm/xe/xe_exec_queue.h
> @@ -66,6 +66,53 @@ static inline bool xe_exec_queue_uses_pxp(struct xe_exec_queue *q)
>  	return q->pxp.type;
>  }
>  
> +/**
> + * xe_exec_queue_is_multi_queue() - Whether an exec_queue is part of a queue group.
> + * @q: The exec_queue
> + *
> + * Return: True if the exec_queue is part of a queue group, false otherwise.
> + */
> +static inline bool xe_exec_queue_is_multi_queue(struct xe_exec_queue *q)
> +{
> +	return q->multi_queue.valid;
> +}
> +
> +/**
> + * xe_exec_queue_is_multi_queue_primary() - Whether an exec_queue is primary queue
> + * of a multi queue group.
> + * @q: The exec_queue
> + *
> + * Return: True if @q is primary queue of a queue group, false otherwise.
> + */
> +static inline bool xe_exec_queue_is_multi_queue_primary(struct xe_exec_queue *q)
> +{
> +	return q->multi_queue.is_primary;
> +}
> +
> +/**
> + * xe_exec_queue_is_multi_queue_secondary() - Whether an exec_queue is secondary queue
> + * of a multi queue group.
> + * @q: The exec_queue
> + *
> + * Return: True if @q is secondary queue of a queue group, false otherwise.
> + */
> +static inline bool xe_exec_queue_is_multi_queue_secondary(struct xe_exec_queue *q)
> +{
> +	return xe_exec_queue_is_multi_queue(q) && !xe_exec_queue_is_multi_queue_primary(q);
> +}
> +
> +/**
> + * xe_exec_queue_multi_queue_primary() - Get multi queue group's primary queue
> + * @q: The exec_queue
> + *
> + * If @q belongs to a multi queue group, then the primary queue of the group will
> + * be returned. Otherwise, @q will be returned.
> + */
> +static inline struct xe_exec_queue *xe_exec_queue_multi_queue_primary(struct xe_exec_queue *q)
> +{
> +	return xe_exec_queue_is_multi_queue(q) ? q->multi_queue.group->primary : q;
> +}
> +
>  bool xe_exec_queue_is_lr(struct xe_exec_queue *q);
>  
>  bool xe_exec_queue_is_idle(struct xe_exec_queue *q);
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> index 771ffe35cd0c..f429b1952be9 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> @@ -32,6 +32,20 @@ enum xe_exec_queue_priority {
>  	XE_EXEC_QUEUE_PRIORITY_COUNT
>  };
>  
> +/**
> + * struct xe_exec_queue_group - Execution multi queue group
> + *
> + * Contains multi queue group information.
> + */
> +struct xe_exec_queue_group {
> +	/** @primary: Primary queue of this group */
> +	struct xe_exec_queue *primary;
> +	/** @cgp_bo: BO for the Context Group Page */
> +	struct xe_bo *cgp_bo;
> +	/** @xa: xarray to store LRCs */
> +	struct xarray xa;
> +};
> +
>  /**
>   * struct xe_exec_queue - Execution queue
>   *
> @@ -111,6 +125,18 @@ struct xe_exec_queue {
>  		struct xe_guc_exec_queue *guc;
>  	};
>  
> +	/** @multi_queue: Multi queue information */
> +	struct {
> +		/** @multi_queue.group: Queue group information */
> +		struct xe_exec_queue_group *group;
> +		/** @multi_queue.pos: Position of queue within the multi-queue group */
> +		u8 pos;
> +		/** @multi_queue.valid: Queue belongs to a multi queue group */
> +		u8 valid:1;
> +		/** @multi_queue.is_primary: Is primary queue (Q0) of the group */
> +		u8 is_primary:1;
> +	} multi_queue;
> +
>  	/** @sched_props: scheduling properties */
>  	struct {
>  		/** @sched_props.timeslice_us: timeslice period in micro-seconds */
> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> index 47853659a705..4de21e0a4fcf 100644
> --- a/include/uapi/drm/xe_drm.h
> +++ b/include/uapi/drm/xe_drm.h
> @@ -1252,6 +1252,14 @@ struct drm_xe_vm_bind {
>   *    Given that going into a power-saving state kills PXP HWDRM sessions,
>   *    runtime PM will be blocked while queues of this type are alive.
>   *    All PXP queues will be killed if a PXP invalidation event occurs.
> + *  - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP - Create a multi-queue group
> + *    or add secondary queues to a multi-queue group.
> + *    If the extension's 'value' field has %DRM_XE_MULTI_GROUP_CREATE flag set,
> + *    then a new multi-queue group is created with this queue as the primary queue
> + *    (Q0). Otherwise, the queue gets added to the multi-queue group whose primary
> + *    queue's exec_queue_id is specified in the lower 32 bits of the 'value' field.
> + *    All the other non-relevant bits of extension's 'value' field while adding the
> + *    primary or the secondary queues of the group must be set to 0.
>   *
>   * The example below shows how to use @drm_xe_exec_queue_create to create
>   * a simple exec_queue (no parallel submission) of class
> @@ -1292,6 +1300,8 @@ struct drm_xe_exec_queue_create {
>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY		0
>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE		1
>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE		2
> +#define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP		3
> +#define     DRM_XE_MULTI_GROUP_CREATE				(1ull << 63)
>  	/** @extensions: Pointer to the first extension struct, if any */
>  	__u64 extensions;
>  
> -- 
> 2.43.0
> 

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

* Re: [PATCH v3 04/18] drm/xe/multi_queue: Add multi queue priority property
  2025-11-21  3:51 ` [PATCH v3 04/18] drm/xe/multi_queue: Add multi queue priority property Niranjana Vishwanathapura
@ 2025-11-21 22:57   ` Matthew Brost
  0 siblings, 0 replies; 41+ messages in thread
From: Matthew Brost @ 2025-11-21 22:57 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

On Thu, Nov 20, 2025 at 07:51:38PM -0800, Niranjana Vishwanathapura wrote:
> Add support for queues of a multi queue group to set
> their priority within the queue group by adding property
> DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY.
> This is the only other property supported by secondary
> queues of a multi queue group, other than
> DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE.
> 
> v2: Add kernel doc for enum xe_multi_queue_priority,
>     Add assert for priority values, fix includes and
>     declarations (Matt Brost)
> v3: update uapi kernel-doc (Matt Brost)
> 
> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> ---
>  drivers/gpu/drm/xe/xe_exec_queue.c       | 17 +++++++++++++-
>  drivers/gpu/drm/xe/xe_exec_queue_types.h | 16 +++++++++++++
>  drivers/gpu/drm/xe/xe_guc_submit.c       |  1 +
>  drivers/gpu/drm/xe/xe_lrc.c              | 29 ++++++++++++++++++++++++
>  drivers/gpu/drm/xe/xe_lrc.h              |  3 +++
>  include/uapi/drm/xe_drm.h                |  4 ++++
>  6 files changed, 69 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
> index 330b5103222c..6debcae8ce11 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue.c
> +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
> @@ -179,6 +179,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
>  	INIT_LIST_HEAD(&q->multi_gt_link);
>  	INIT_LIST_HEAD(&q->hw_engine_group_link);
>  	INIT_LIST_HEAD(&q->pxp.link);
> +	q->multi_queue.priority = XE_MULTI_QUEUE_PRIORITY_NORMAL;
>  
>  	q->sched_props.timeslice_us = hwe->eclass->sched_props.timeslice_us;
>  	q->sched_props.preempt_timeout_us =
> @@ -740,6 +741,17 @@ static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue
>  	return xe_exec_queue_group_validate(xe, q, value);
>  }
>  
> +static int exec_queue_set_multi_queue_priority(struct xe_device *xe, struct xe_exec_queue *q,
> +					       u64 value)
> +{
> +	if (XE_IOCTL_DBG(xe, value > XE_MULTI_QUEUE_PRIORITY_HIGH))
> +		return -EINVAL;
> +
> +	q->multi_queue.priority = value;
> +
> +	return 0;
> +}
> +
>  typedef int (*xe_exec_queue_set_property_fn)(struct xe_device *xe,
>  					     struct xe_exec_queue *q,
>  					     u64 value);
> @@ -749,6 +761,8 @@ static const xe_exec_queue_set_property_fn exec_queue_set_property_funcs[] = {
>  	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE] = exec_queue_set_timeslice,
>  	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE] = exec_queue_set_pxp_type,
>  	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP] = exec_queue_set_multi_group,
> +	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY] =
> +							exec_queue_set_multi_queue_priority,
>  };
>  
>  static int exec_queue_user_ext_set_property(struct xe_device *xe,
> @@ -770,7 +784,8 @@ static int exec_queue_user_ext_set_property(struct xe_device *xe,
>  	    XE_IOCTL_DBG(xe, ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY &&
>  			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE &&
>  			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE &&
> -			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP))
> +			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP &&
> +			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY))
>  		return -EINVAL;
>  
>  	idx = array_index_nospec(ext.property, ARRAY_SIZE(exec_queue_set_property_funcs));
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> index b9da51ab7eaf..445ae4979c0c 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> @@ -32,6 +32,20 @@ enum xe_exec_queue_priority {
>  	XE_EXEC_QUEUE_PRIORITY_COUNT
>  };
>  
> +/**
> + * enum xe_multi_queue_priority - Multi Queue priority values
> + *
> + * The priority values of the queues within the multi queue group.
> + */
> +enum xe_multi_queue_priority {
> +	/** @XE_MULTI_QUEUE_PRIORITY_LOW: Priority low */
> +	XE_MULTI_QUEUE_PRIORITY_LOW = 0,
> +	/** @XE_MULTI_QUEUE_PRIORITY_NORMAL: Priority normal */
> +	XE_MULTI_QUEUE_PRIORITY_NORMAL,
> +	/** @XE_MULTI_QUEUE_PRIORITY_HIGH: Priority high */
> +	XE_MULTI_QUEUE_PRIORITY_HIGH,
> +};
> +
>  /**
>   * struct xe_exec_queue_group - Execution multi queue group
>   *
> @@ -131,6 +145,8 @@ struct xe_exec_queue {
>  	struct {
>  		/** @multi_queue.group: Queue group information */
>  		struct xe_exec_queue_group *group;
> +		/** @multi_queue.priority: Queue priority within the multi-queue group */
> +		enum xe_multi_queue_priority priority;
>  		/** @multi_queue.pos: Position of queue within the multi-queue group */
>  		u8 pos;
>  		/** @multi_queue.valid: Queue belongs to a multi queue group */
> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
> index c68739fd7592..8a75d0ed7ee9 100644
> --- a/drivers/gpu/drm/xe/xe_guc_submit.c
> +++ b/drivers/gpu/drm/xe/xe_guc_submit.c
> @@ -638,6 +638,7 @@ static void xe_guc_exec_queue_group_cgp_sync(struct xe_guc *guc,
>  		return;
>  	}
>  
> +	xe_lrc_set_multi_queue_priority(q->lrc[0], q->multi_queue.priority);
>  	xe_guc_exec_queue_group_cgp_update(xe, q);
>  
>  	WRITE_ONCE(group->sync_pending, true);
> diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c
> index b5083c99dd50..56836a5546d8 100644
> --- a/drivers/gpu/drm/xe/xe_lrc.c
> +++ b/drivers/gpu/drm/xe/xe_lrc.c
> @@ -44,6 +44,11 @@
>  #define LRC_INDIRECT_CTX_BO_SIZE		SZ_4K
>  #define LRC_INDIRECT_RING_STATE_SIZE		SZ_4K
>  
> +#define LRC_PRIORITY				GENMASK_ULL(10, 9)
> +#define LRC_PRIORITY_LOW			0
> +#define LRC_PRIORITY_NORMAL			1
> +#define LRC_PRIORITY_HIGH			2
> +
>  /*
>   * Layout of the LRC and associated data allocated as
>   * lrc->bo:
> @@ -1386,6 +1391,30 @@ setup_indirect_ctx(struct xe_lrc *lrc, struct xe_hw_engine *hwe)
>  	return 0;
>  }
>  
> +static u8 xe_multi_queue_prio_to_lrc(struct xe_lrc *lrc, enum xe_multi_queue_priority priority)
> +{
> +	struct xe_device *xe = gt_to_xe(lrc->gt);
> +
> +	xe_assert(xe, (priority >= XE_MULTI_QUEUE_PRIORITY_LOW &&
> +		       priority <= XE_MULTI_QUEUE_PRIORITY_HIGH));
> +
> +	/* xe_multi_queue_priority is directly mapped to LRC priority values */
> +	return priority;
> +}
> +
> +/**
> + * xe_lrc_set_multi_queue_priority() - Set multi queue priority in LRC
> + * @lrc: Logical Ring Context
> + * @priority: Multi queue priority of the exec queue
> + *
> + * Convert @priority to LRC multi queue priority and update the @lrc descriptor
> + */
> +void xe_lrc_set_multi_queue_priority(struct xe_lrc *lrc, enum xe_multi_queue_priority priority)
> +{
> +	lrc->desc &= ~LRC_PRIORITY;
> +	lrc->desc |= FIELD_PREP(LRC_PRIORITY, xe_multi_queue_prio_to_lrc(lrc, priority));
> +}
> +
>  static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe,
>  		       struct xe_vm *vm, u32 ring_size, u16 msix_vec,
>  		       u32 init_flags)
> diff --git a/drivers/gpu/drm/xe/xe_lrc.h b/drivers/gpu/drm/xe/xe_lrc.h
> index 2fb628da5c43..569ca380676e 100644
> --- a/drivers/gpu/drm/xe/xe_lrc.h
> +++ b/drivers/gpu/drm/xe/xe_lrc.h
> @@ -13,6 +13,7 @@ struct drm_printer;
>  struct xe_bb;
>  struct xe_device;
>  struct xe_exec_queue;
> +enum xe_multi_queue_priority;
>  enum xe_engine_class;
>  struct xe_gt;
>  struct xe_hw_engine;
> @@ -133,6 +134,8 @@ void xe_lrc_dump_default(struct drm_printer *p,
>  
>  u32 *xe_lrc_emit_hwe_state_instructions(struct xe_exec_queue *q, u32 *cs);
>  
> +void xe_lrc_set_multi_queue_priority(struct xe_lrc *lrc, enum xe_multi_queue_priority priority);
> +
>  struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc);
>  void xe_lrc_snapshot_capture_delayed(struct xe_lrc_snapshot *snapshot);
>  void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer *p);
> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> index 4de21e0a4fcf..240eeea99cb0 100644
> --- a/include/uapi/drm/xe_drm.h
> +++ b/include/uapi/drm/xe_drm.h
> @@ -1260,6 +1260,9 @@ struct drm_xe_vm_bind {
>   *    queue's exec_queue_id is specified in the lower 32 bits of the 'value' field.
>   *    All the other non-relevant bits of extension's 'value' field while adding the
>   *    primary or the secondary queues of the group must be set to 0.
> + *  - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY - Set the queue
> + *    priority within the multi-queue group. Current valid priority values are 0–2
> + *    (default is 1), with higher values indicating higher priority.
>   *
>   * The example below shows how to use @drm_xe_exec_queue_create to create
>   * a simple exec_queue (no parallel submission) of class
> @@ -1302,6 +1305,7 @@ struct drm_xe_exec_queue_create {
>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE		2
>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP		3
>  #define     DRM_XE_MULTI_GROUP_CREATE				(1ull << 63)
> +#define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY	4
>  	/** @extensions: Pointer to the first extension struct, if any */
>  	__u64 extensions;
>  
> -- 
> 2.43.0
> 

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

* Re: [PATCH v3 09/18] drm/xe/multi_queue: Handle tearing down of a multi queue
  2025-11-21  3:51 ` [PATCH v3 09/18] drm/xe/multi_queue: Handle tearing down of a multi queue Niranjana Vishwanathapura
@ 2025-11-21 23:03   ` Matthew Brost
  2025-11-22  4:40     ` Niranjana Vishwanathapura
  2025-11-22  5:47   ` Matthew Brost
  1 sibling, 1 reply; 41+ messages in thread
From: Matthew Brost @ 2025-11-21 23:03 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

On Thu, Nov 20, 2025 at 07:51:43PM -0800, Niranjana Vishwanathapura wrote:
> As all queues of a multi queue group use the primary queue of the group
> to interface with GuC. Hence there is a dependency between the queues of
> the group. So, when primary queue of a multi queue group is cleaned up,
> also trigger a cleanup of the secondary queues also. During cleanup, stop
> and re-start submission for all queues of a multi queue group to avoid
> any submission happening in parallel when a queue is being cleaned up.
> 
> v2: Initialize group->list_lock, add fs_reclaim dependency, remove
>     unwanted secondary queues cleanup (Matt Brost)
> v3: Properly handle cleanup of multi-queue group (Matt Brost)
> 
> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_exec_queue.c       |  10 ++
>  drivers/gpu/drm/xe/xe_exec_queue_types.h |   6 +
>  drivers/gpu/drm/xe/xe_guc_submit.c       | 154 ++++++++++++++++++-----
>  3 files changed, 142 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
> index cdc044d3c96c..ab161b74fef0 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue.c
> +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
> @@ -87,6 +87,7 @@ static void xe_exec_queue_group_cleanup(struct xe_exec_queue *q)
>  		xe_lrc_put(lrc);
>  
>  	xa_destroy(&group->xa);
> +	mutex_destroy(&group->list_lock);
>  	xe_bo_unpin_map_no_vm(group->cgp_bo);
>  	kfree(group);
>  }
> @@ -627,9 +628,18 @@ static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue *
>  
>  	group->primary = q;
>  	group->cgp_bo = bo;
> +	INIT_LIST_HEAD(&group->list);
>  	xa_init_flags(&group->xa, XA_FLAGS_ALLOC1);
> +	mutex_init(&group->list_lock);
>  	q->multi_queue.group = group;
>  
> +	/* group->list_lock is used in submission backend */
> +	if (!IS_ENABLED(CONFIG_LOCKDEP)) {

I believe the polarity is inverted above.

Everything else LGTM.

Matt

> +		fs_reclaim_acquire(GFP_KERNEL);
> +		might_lock(&group->list_lock);
> +		fs_reclaim_release(GFP_KERNEL);
> +	}
> +
>  	return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> index cafb3ba9a123..5721fb4bad1a 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> @@ -58,6 +58,10 @@ struct xe_exec_queue_group {
>  	struct xe_bo *cgp_bo;
>  	/** @xa: xarray to store LRCs */
>  	struct xarray xa;
> +	/** @list: List of all secondary queues in the group */
> +	struct list_head list;
> +	/** @list_lock: Secondary queue list lock */
> +	struct mutex list_lock;
>  	/** @sync_pending: CGP_SYNC_DONE g2h response pending */
>  	bool sync_pending;
>  };
> @@ -145,6 +149,8 @@ struct xe_exec_queue {
>  	struct {
>  		/** @multi_queue.group: Queue group information */
>  		struct xe_exec_queue_group *group;
> +		/** @multi_queue.link: Link into group's secondary queues list */
> +		struct list_head link;
>  		/** @multi_queue.priority: Queue priority within the multi-queue group */
>  		enum xe_multi_queue_priority priority;
>  		/** @multi_queue.pos: Position of queue within the multi-queue group */
> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
> index ce870a119800..2e5fff7ad69b 100644
> --- a/drivers/gpu/drm/xe/xe_guc_submit.c
> +++ b/drivers/gpu/drm/xe/xe_guc_submit.c
> @@ -577,6 +577,45 @@ static bool vf_recovery(struct xe_guc *guc)
>  	return xe_gt_recovery_pending(guc_to_gt(guc));
>  }
>  
> +static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
> +{
> +	struct xe_guc *guc = exec_queue_to_guc(q);
> +	struct xe_device *xe = guc_to_xe(guc);
> +
> +	/** to wakeup xe_wait_user_fence ioctl if exec queue is reset */
> +	wake_up_all(&xe->ufence_wq);
> +
> +	if (xe_exec_queue_is_lr(q))
> +		queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr);
> +	else
> +		xe_sched_tdr_queue_imm(&q->guc->sched);
> +}
> +
> +static void xe_guc_exec_queue_reset_trigger_cleanup(struct xe_exec_queue *q)
> +{
> +	if (xe_exec_queue_is_multi_queue(q)) {
> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
> +		struct xe_exec_queue_group *group = q->multi_queue.group;
> +		struct xe_exec_queue *eq;
> +
> +		set_exec_queue_reset(primary);
> +		if (!exec_queue_banned(primary) && !exec_queue_check_timeout(primary))
> +			xe_guc_exec_queue_trigger_cleanup(primary);
> +
> +		mutex_lock(&group->list_lock);
> +		list_for_each_entry(eq, &group->list, multi_queue.link) {
> +			set_exec_queue_reset(eq);
> +			if (!exec_queue_banned(eq) && !exec_queue_check_timeout(eq))
> +				xe_guc_exec_queue_trigger_cleanup(eq);
> +		}
> +		mutex_unlock(&group->list_lock);
> +	} else {
> +		set_exec_queue_reset(q);
> +		if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
> +			xe_guc_exec_queue_trigger_cleanup(q);
> +	}
> +}
> +
>  #define parallel_read(xe_, map_, field_) \
>  	xe_map_rd_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
>  			field_)
> @@ -939,6 +978,50 @@ static void wq_item_append(struct xe_exec_queue *q)
>  	parallel_write(xe, map, wq_desc.tail, q->guc->wqi_tail);
>  }
>  
> +static void xe_guc_exec_queue_submission_start(struct xe_exec_queue *q)
> +{
> +	/*
> +	 * If the exec queue is part of a multi queue group, then start submission
> +	 * on all queues of the multi queue group.
> +	 */
> +	if (xe_exec_queue_is_multi_queue(q)) {
> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
> +		struct xe_exec_queue_group *group = q->multi_queue.group;
> +		struct xe_exec_queue *eq;
> +
> +		xe_sched_submission_start(&primary->guc->sched);
> +
> +		mutex_lock(&group->list_lock);
> +		list_for_each_entry(eq, &group->list, multi_queue.link)
> +			xe_sched_submission_start(&eq->guc->sched);
> +		mutex_unlock(&group->list_lock);
> +	} else {
> +		xe_sched_submission_start(&q->guc->sched);
> +	}
> +}
> +
> +static void xe_guc_exec_queue_submission_stop(struct xe_exec_queue *q)
> +{
> +	/*
> +	 * If the exec queue is part of a multi queue group, then stop submission
> +	 * on all queues of the multi queue group.
> +	 */
> +	if (xe_exec_queue_is_multi_queue(q)) {
> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
> +		struct xe_exec_queue_group *group = q->multi_queue.group;
> +		struct xe_exec_queue *eq;
> +
> +		xe_sched_submission_stop(&primary->guc->sched);
> +
> +		mutex_lock(&group->list_lock);
> +		list_for_each_entry(eq, &group->list, multi_queue.link)
> +			xe_sched_submission_stop(&eq->guc->sched);
> +		mutex_unlock(&group->list_lock);
> +	} else {
> +		xe_sched_submission_stop(&q->guc->sched);
> +	}
> +}
> +
>  #define RESUME_PENDING	~0x0ull
>  static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job)
>  {
> @@ -1117,20 +1200,6 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
>  			       G2H_LEN_DW_DEREGISTER_CONTEXT, 2);
>  }
>  
> -static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
> -{
> -	struct xe_guc *guc = exec_queue_to_guc(q);
> -	struct xe_device *xe = guc_to_xe(guc);
> -
> -	/** to wakeup xe_wait_user_fence ioctl if exec queue is reset */
> -	wake_up_all(&xe->ufence_wq);
> -
> -	if (xe_exec_queue_is_lr(q))
> -		queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr);
> -	else
> -		xe_sched_tdr_queue_imm(&q->guc->sched);
> -}
> -
>  /**
>   * xe_guc_submit_wedge() - Wedge GuC submission
>   * @guc: the GuC object
> @@ -1204,8 +1273,12 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
>  	if (!exec_queue_killed(q))
>  		wedged = guc_submit_hint_wedged(exec_queue_to_guc(q));
>  
> -	/* Kill the run_job / process_msg entry points */
> -	xe_sched_submission_stop(sched);
> +	/*
> +	 * Kill the run_job / process_msg entry points.
> +	 * As this function is serialized across exec queues, it is safe to
> +	 * stop and restart submission on all queues of a multi queue group.
> +	 */
> +	xe_guc_exec_queue_submission_stop(q);
>  
>  	/*
>  	 * Engine state now mostly stable, disable scheduling / deregister if
> @@ -1241,7 +1314,7 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
>  				   q->guc->id);
>  			xe_devcoredump(q, NULL, "Schedule disable failed to respond, guc_id=%d\n",
>  				       q->guc->id);
> -			xe_sched_submission_start(sched);
> +			xe_guc_exec_queue_submission_start(q);
>  			xe_gt_reset_async(q->gt);
>  			return;
>  		}
> @@ -1252,7 +1325,7 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
>  
>  	xe_hw_fence_irq_stop(q->fence_irq);
>  
> -	xe_sched_submission_start(sched);
> +	xe_guc_exec_queue_submission_start(q);
>  
>  	spin_lock(&sched->base.job_list_lock);
>  	list_for_each_entry(job, &sched->base.pending_list, drm.list)
> @@ -1410,8 +1483,12 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
>  	    vf_recovery(guc))
>  		return DRM_GPU_SCHED_STAT_NO_HANG;
>  
> -	/* Kill the run_job entry point */
> -	xe_sched_submission_stop(sched);
> +	/*
> +	 * Kill the run_job entry point.
> +	 * As this function is serialized across exec queues, it is safe to
> +	 * stop and restart submission on all queues of a multi queue group.
> +	 */
> +	xe_guc_exec_queue_submission_stop(q);
>  
>  	/* Must check all state after stopping scheduler */
>  	skip_timeout_check = exec_queue_reset(q) ||
> @@ -1568,7 +1645,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
>  	 * fences that are complete
>  	 */
>  	xe_sched_add_pending_job(sched, job);
> -	xe_sched_submission_start(sched);
> +	xe_guc_exec_queue_submission_start(q);
>  
>  	xe_guc_exec_queue_trigger_cleanup(q);
>  
> @@ -1592,7 +1669,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
>  	 * but there is not currently an easy way to do in DRM scheduler. With
>  	 * some thought, do this in a follow up.
>  	 */
> -	xe_sched_submission_start(sched);
> +	xe_guc_exec_queue_submission_start(q);
>  handle_vf_resume:
>  	return DRM_GPU_SCHED_STAT_NO_HANG;
>  }
> @@ -1623,6 +1700,14 @@ static void __guc_exec_queue_destroy_async(struct work_struct *w)
>  	guard(xe_pm_runtime)(guc_to_xe(guc));
>  	trace_xe_exec_queue_destroy(q);
>  
> +	if (xe_exec_queue_is_multi_queue_secondary(q)) {
> +		struct xe_exec_queue_group *group = q->multi_queue.group;
> +
> +		mutex_lock(&group->list_lock);
> +		list_del(&q->multi_queue.link);
> +		mutex_unlock(&group->list_lock);
> +	}
> +
>  	if (xe_exec_queue_is_lr(q))
>  		cancel_work_sync(&ge->lr_tdr);
>  	/* Confirm no work left behind accessing device structures */
> @@ -1913,6 +1998,19 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
>  
>  	xe_exec_queue_assign_name(q, q->guc->id);
>  
> +	/*
> +	 * Maintain secondary queues of the multi queue group in a list
> +	 * for handling dependencies across the queues in the group.
> +	 */
> +	if (xe_exec_queue_is_multi_queue_secondary(q)) {
> +		struct xe_exec_queue_group *group = q->multi_queue.group;
> +
> +		INIT_LIST_HEAD(&q->multi_queue.link);
> +		mutex_lock(&group->list_lock);
> +		list_add_tail(&q->multi_queue.link, &group->list);
> +		mutex_unlock(&group->list_lock);
> +	}
> +
>  	trace_xe_exec_queue_create(q);
>  
>  	return 0;
> @@ -2140,6 +2238,10 @@ static void guc_exec_queue_resume(struct xe_exec_queue *q)
>  
>  static bool guc_exec_queue_reset_status(struct xe_exec_queue *q)
>  {
> +	if (xe_exec_queue_is_multi_queue_secondary(q) &&
> +	    guc_exec_queue_reset_status(xe_exec_queue_multi_queue_primary(q)))
> +		return true;
> +
>  	return exec_queue_reset(q) || exec_queue_killed_or_banned_or_wedged(q);
>  }
>  
> @@ -2801,9 +2903,7 @@ int xe_guc_exec_queue_reset_handler(struct xe_guc *guc, u32 *msg, u32 len)
>  	 * jobs by setting timeout of the job to the minimum value kicking
>  	 * guc_exec_queue_timedout_job.
>  	 */
> -	set_exec_queue_reset(q);
> -	if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
> -		xe_guc_exec_queue_trigger_cleanup(q);
> +	xe_guc_exec_queue_reset_trigger_cleanup(q);
>  
>  	return 0;
>  }
> @@ -2882,9 +2982,7 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg,
>  	trace_xe_exec_queue_memory_cat_error(q);
>  
>  	/* Treat the same as engine reset */
> -	set_exec_queue_reset(q);
> -	if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
> -		xe_guc_exec_queue_trigger_cleanup(q);
> +	xe_guc_exec_queue_reset_trigger_cleanup(q);
>  
>  	return 0;
>  }
> -- 
> 2.43.0
> 

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

* Re: [PATCH v3 12/18] drm/xe/multi_queue: Reset GT upon CGP_SYNC failure
  2025-11-21  3:51 ` [PATCH v3 12/18] drm/xe/multi_queue: Reset GT upon CGP_SYNC failure Niranjana Vishwanathapura
@ 2025-11-21 23:08   ` Matthew Brost
  0 siblings, 0 replies; 41+ messages in thread
From: Matthew Brost @ 2025-11-21 23:08 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

On Thu, Nov 20, 2025 at 07:51:46PM -0800, Niranjana Vishwanathapura wrote:
> If GuC doesn't response to CGP_SYNC message, trigger
> GT reset and cleanup of all the queues of the multi
> queue group.
> 
> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> ---
>  drivers/gpu/drm/xe/xe_guc_submit.c | 38 ++++++++++++++++++++++++++++++
>  1 file changed, 38 insertions(+)
> 
> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
> index 87a33c06fe26..932be1e5001e 100644
> --- a/drivers/gpu/drm/xe/xe_guc_submit.c
> +++ b/drivers/gpu/drm/xe/xe_guc_submit.c
> @@ -593,6 +593,23 @@ static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
>  		xe_sched_tdr_queue_imm(&q->guc->sched);
>  }
>  
> +static void xe_guc_exec_queue_group_trigger_cleanup(struct xe_exec_queue *q)
> +{
> +	struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
> +	struct xe_exec_queue_group *group = q->multi_queue.group;
> +	struct xe_exec_queue *eq;
> +
> +	xe_gt_assert(guc_to_gt(exec_queue_to_guc(q)),
> +		     xe_exec_queue_is_multi_queue(q));
> +
> +	xe_guc_exec_queue_trigger_cleanup(primary);
> +
> +	mutex_lock(&group->list_lock);
> +	list_for_each_entry(eq, &group->list, multi_queue.link)
> +		xe_guc_exec_queue_trigger_cleanup(eq);
> +	mutex_unlock(&group->list_lock);
> +}
> +
>  static void xe_guc_exec_queue_reset_trigger_cleanup(struct xe_exec_queue *q)
>  {
>  	if (xe_exec_queue_is_multi_queue(q)) {
> @@ -618,6 +635,23 @@ static void xe_guc_exec_queue_reset_trigger_cleanup(struct xe_exec_queue *q)
>  	}
>  }
>  
> +static void set_exec_queue_group_banned(struct xe_exec_queue *q)
> +{
> +	struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
> +	struct xe_exec_queue_group *group = q->multi_queue.group;
> +	struct xe_exec_queue *eq;
> +
> +	/* Ban all queues of the multi-queue group */
> +	xe_gt_assert(guc_to_gt(exec_queue_to_guc(q)),
> +		     xe_exec_queue_is_multi_queue(q));
> +	set_exec_queue_banned(primary);
> +
> +	mutex_lock(&group->list_lock);
> +	list_for_each_entry(eq, &group->list, multi_queue.link)
> +		set_exec_queue_banned(eq);
> +	mutex_unlock(&group->list_lock);
> +}
> +
>  #define parallel_read(xe_, map_, field_) \
>  	xe_map_rd_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
>  			field_)
> @@ -675,7 +709,11 @@ static void xe_guc_exec_queue_group_cgp_sync(struct xe_guc *guc,
>  				 !READ_ONCE(group->sync_pending) ||
>  				 xe_guc_read_stopped(guc), HZ);
>  	if ((!ret && !vf_recovery(guc)) || xe_guc_read_stopped(guc)) {
> +		/* CGP_SYNC failed. Reset gt, cleanup the group */
>  		xe_gt_warn(guc_to_gt(guc), "Wait for CGP_SYNC_DONE response failed!\n");
> +		set_exec_queue_group_banned(q);
> +		xe_gt_reset_async(q->gt);
> +		xe_guc_exec_queue_group_trigger_cleanup(q);
>  		return;
>  	}
>  
> -- 
> 2.43.0
> 

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

* Re: [PATCH v3 02/18] drm/xe/multi_queue: Add user interface for multi queue support
  2025-11-21 22:51   ` Matthew Brost
@ 2025-11-22  4:35     ` Niranjana Vishwanathapura
  0 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-22  4:35 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe

On Fri, Nov 21, 2025 at 02:51:21PM -0800, Matthew Brost wrote:
>On Thu, Nov 20, 2025 at 07:51:36PM -0800, Niranjana Vishwanathapura wrote:
>> Multi Queue is a new mode of execution supported by the compute and
>> blitter copy command streamers (CCS and BCS, respectively). It is an
>> enhancement of the existing hardware architecture and leverages the
>> same submission model. It enables support for efficient, parallel
>> execution of multiple queues within a single context. All the queues
>> of a group must use the same address space (VM).
>>
>> The new DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE execution queue
>> property supports creating a multi queue group and adding queues to
>> a queue group. All queues of a multi queue group share the same
>> context.
>>
>> A exec queue create ioctl call with above property specified with value
>> DRM_XE_SUPER_GROUP_CREATE will create a new multi queue group with the
>> queue being created as the primary queue (aka q0) of the group. To add
>> secondary queues to the group, they need to be created with the above
>> property with id of the primary queue as the value. The properties of
>> the primary queue (like priority, timeslice) applies to the whole group.
>> So, these properties can't be set for secondary queues of a group.
>>
>> Once destroyed, the secondary queues of a multi queue group can't be
>> replaced. However, they can be dynamically added to the group up to a
>> total of 64 queues per group. Once the primary queue is destroyed,
>> secondary queues can't be added to the queue group.
>>
>> v2: Remove group->lock, fix xe_exec_queue_group_add()/delete()
>>     function semantics, add additional comments, remove unused
>>     group->list_lock, add XE_BO_FLAG_GGTT_INVALIDATE for cgp bo,
>>     Assert LRC is valid, update uapi kernel doc.
>>     (Matt Brost)
>> v3: Use XE_BO_FLAG_PINNED_LATE_RESTORE/USER_VRAM/GGTT_INVALIDATE
>>     flags for cgp bo (Matt)
>>
>> Signed-off-by: Stuart Summers <stuart.summers@intel.com>
>> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
>
>Reviewed-by: Matthew Brost <matthew.brost@intel.com>
>
>As this is new uAPI we will need a UMD PR and ack from a UMD team.
>

Thanks.
I have added the link to UMD PR in the cover letter.
https://github.com/intel/compute-runtime/pull/862.
Will check with UMD team for ack.

>Matt
>
>> ---
>>  drivers/gpu/drm/xe/xe_exec_queue.c       | 194 ++++++++++++++++++++++-
>>  drivers/gpu/drm/xe/xe_exec_queue.h       |  47 ++++++
>>  drivers/gpu/drm/xe/xe_exec_queue_types.h |  26 +++
>>  include/uapi/drm/xe_drm.h                |  10 ++
>>  4 files changed, 275 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
>> index 8724f8de67e2..330b5103222c 100644
>> --- a/drivers/gpu/drm/xe/xe_exec_queue.c
>> +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
>> @@ -13,6 +13,7 @@
>>  #include <drm/drm_syncobj.h>
>>  #include <uapi/drm/xe_drm.h>
>>
>> +#include "xe_bo.h"
>>  #include "xe_dep_scheduler.h"
>>  #include "xe_device.h"
>>  #include "xe_gt.h"
>> @@ -63,6 +64,33 @@ enum xe_exec_queue_sched_prop {
>>  static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue *q,
>>  				      u64 extensions, int ext_number);
>>
>> +static void xe_exec_queue_group_cleanup(struct xe_exec_queue *q)
>> +{
>> +	struct xe_exec_queue_group *group = q->multi_queue.group;
>> +	struct xe_lrc *lrc;
>> +	unsigned long idx;
>> +
>> +	if (xe_exec_queue_is_multi_queue_secondary(q)) {
>> +		/*
>> +		 * Put pairs with get from xe_exec_queue_lookup() call
>> +		 * in xe_exec_queue_group_validate().
>> +		 */
>> +		xe_exec_queue_put(xe_exec_queue_multi_queue_primary(q));
>> +		return;
>> +	}
>> +
>> +	if (!group)
>> +		return;
>> +
>> +	/* Primary queue cleanup */
>> +	xa_for_each(&group->xa, idx, lrc)
>> +		xe_lrc_put(lrc);
>> +
>> +	xa_destroy(&group->xa);
>> +	xe_bo_unpin_map_no_vm(group->cgp_bo);
>> +	kfree(group);
>> +}
>> +
>>  static void __xe_exec_queue_free(struct xe_exec_queue *q)
>>  {
>>  	int i;
>> @@ -73,6 +101,10 @@ static void __xe_exec_queue_free(struct xe_exec_queue *q)
>>
>>  	if (xe_exec_queue_uses_pxp(q))
>>  		xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q);
>> +
>> +	if (xe_exec_queue_is_multi_queue(q))
>> +		xe_exec_queue_group_cleanup(q);
>> +
>>  	if (q->vm)
>>  		xe_vm_put(q->vm);
>>
>> @@ -567,6 +599,147 @@ exec_queue_set_pxp_type(struct xe_device *xe, struct xe_exec_queue *q, u64 value
>>  	return xe_pxp_exec_queue_set_type(xe->pxp, q, DRM_XE_PXP_TYPE_HWDRM);
>>  }
>>
>> +static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue *q)
>> +{
>> +	struct xe_tile *tile = gt_to_tile(q->gt);
>> +	struct xe_exec_queue_group *group;
>> +	struct xe_bo *bo;
>> +
>> +	group = kzalloc(sizeof(*group), GFP_KERNEL);
>> +	if (!group)
>> +		return -ENOMEM;
>> +
>> +	bo = xe_bo_create_pin_map_novm(xe, tile, SZ_4K, ttm_bo_type_kernel,
>> +				       XE_BO_FLAG_VRAM_IF_DGFX(tile) |
>> +				       XE_BO_FLAG_PINNED_LATE_RESTORE |
>> +				       XE_BO_FLAG_FORCE_USER_VRAM |
>> +				       XE_BO_FLAG_GGTT_INVALIDATE |
>> +				       XE_BO_FLAG_GGTT, false);
>> +	if (IS_ERR(bo)) {
>> +		drm_err(&xe->drm, "CGP bo allocation for queue group failed: %ld\n",
>> +			PTR_ERR(bo));
>> +		kfree(group);
>> +		return PTR_ERR(bo);
>> +	}
>> +
>> +	xe_map_memset(xe, &bo->vmap, 0, 0, SZ_4K);
>> +
>> +	group->primary = q;
>> +	group->cgp_bo = bo;
>> +	xa_init_flags(&group->xa, XA_FLAGS_ALLOC1);
>> +	q->multi_queue.group = group;
>> +
>> +	return 0;
>> +}
>> +
>> +static inline bool xe_exec_queue_supports_multi_queue(struct xe_exec_queue *q)
>> +{
>> +	return q->gt->info.multi_queue_engine_class_mask & BIT(q->class);
>> +}
>> +
>> +static int xe_exec_queue_group_validate(struct xe_device *xe, struct xe_exec_queue *q,
>> +					u32 primary_id)
>> +{
>> +	struct xe_exec_queue_group *group;
>> +	struct xe_exec_queue *primary;
>> +	int ret;
>> +
>> +	/*
>> +	 * Get from below xe_exec_queue_lookup() pairs with put
>> +	 * in xe_exec_queue_group_cleanup().
>> +	 */
>> +	primary = xe_exec_queue_lookup(q->vm->xef, primary_id);
>> +	if (XE_IOCTL_DBG(xe, !primary))
>> +		return -ENOENT;
>> +
>> +	if (XE_IOCTL_DBG(xe, !xe_exec_queue_is_multi_queue_primary(primary)) ||
>> +	    XE_IOCTL_DBG(xe, q->vm != primary->vm) ||
>> +	    XE_IOCTL_DBG(xe, q->logical_mask != primary->logical_mask)) {
>> +		ret = -EINVAL;
>> +		goto put_primary;
>> +	}
>> +
>> +	group = primary->multi_queue.group;
>> +	q->multi_queue.valid = true;
>> +	q->multi_queue.group = group;
>> +
>> +	return 0;
>> +put_primary:
>> +	xe_exec_queue_put(primary);
>> +	return ret;
>> +}
>> +
>> +#define XE_MAX_GROUP_SIZE	64
>> +static int xe_exec_queue_group_add(struct xe_device *xe, struct xe_exec_queue *q)
>> +{
>> +	struct xe_exec_queue_group *group = q->multi_queue.group;
>> +	u32 pos;
>> +	int err;
>> +
>> +	xe_assert(xe, xe_exec_queue_is_multi_queue_secondary(q));
>> +
>> +	/* Primary queue holds a reference to LRCs of all secondary queues */
>> +	err = xa_alloc(&group->xa, &pos, xe_lrc_get(q->lrc[0]),
>> +		       XA_LIMIT(1, XE_MAX_GROUP_SIZE - 1), GFP_KERNEL);
>> +	if (XE_IOCTL_DBG(xe, err)) {
>> +		xe_lrc_put(q->lrc[0]);
>> +
>> +		/* It is invalid if queue group limit is exceeded */
>> +		if (err == -EBUSY)
>> +			err = -EINVAL;
>> +
>> +		return err;
>> +	}
>> +
>> +	q->multi_queue.pos = pos;
>> +
>> +	return 0;
>> +}
>> +
>> +static void xe_exec_queue_group_delete(struct xe_device *xe, struct xe_exec_queue *q)
>> +{
>> +	struct xe_exec_queue_group *group = q->multi_queue.group;
>> +	struct xe_lrc *lrc;
>> +
>> +	xe_assert(xe, xe_exec_queue_is_multi_queue_secondary(q));
>> +
>> +	lrc = xa_erase(&group->xa, q->multi_queue.pos);
>> +	xe_assert(xe, lrc);
>> +	xe_lrc_put(lrc);
>> +}
>> +
>> +static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue *q,
>> +				      u64 value)
>> +{
>> +	if (XE_IOCTL_DBG(xe, !xe_exec_queue_supports_multi_queue(q)))
>> +		return -ENODEV;
>> +
>> +	if (XE_IOCTL_DBG(xe, !xe_device_uc_enabled(xe)))
>> +		return -EOPNOTSUPP;
>> +
>> +	if (XE_IOCTL_DBG(xe, xe_exec_queue_is_parallel(q)))
>> +		return -EINVAL;
>> +
>> +	if (XE_IOCTL_DBG(xe, xe_exec_queue_is_multi_queue(q)))
>> +		return -EINVAL;
>> +
>> +	if (value & DRM_XE_MULTI_GROUP_CREATE) {
>> +		if (XE_IOCTL_DBG(xe, value & ~DRM_XE_MULTI_GROUP_CREATE))
>> +			return -EINVAL;
>> +
>> +		q->multi_queue.valid = true;
>> +		q->multi_queue.is_primary = true;
>> +		q->multi_queue.pos = 0;
>> +		return 0;
>> +	}
>> +
>> +	/* While adding secondary queues, the upper 32 bits must be 0 */
>> +	if (XE_IOCTL_DBG(xe, value & (~0ull << 32)))
>> +		return -EINVAL;
>> +
>> +	return xe_exec_queue_group_validate(xe, q, value);
>> +}
>> +
>>  typedef int (*xe_exec_queue_set_property_fn)(struct xe_device *xe,
>>  					     struct xe_exec_queue *q,
>>  					     u64 value);
>> @@ -575,6 +748,7 @@ static const xe_exec_queue_set_property_fn exec_queue_set_property_funcs[] = {
>>  	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY] = exec_queue_set_priority,
>>  	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE] = exec_queue_set_timeslice,
>>  	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE] = exec_queue_set_pxp_type,
>> +	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP] = exec_queue_set_multi_group,
>>  };
>>
>>  static int exec_queue_user_ext_set_property(struct xe_device *xe,
>> @@ -595,7 +769,8 @@ static int exec_queue_user_ext_set_property(struct xe_device *xe,
>>  	    XE_IOCTL_DBG(xe, ext.pad) ||
>>  	    XE_IOCTL_DBG(xe, ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY &&
>>  			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE &&
>> -			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE))
>> +			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE &&
>> +			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP))
>>  		return -EINVAL;
>>
>>  	idx = array_index_nospec(ext.property, ARRAY_SIZE(exec_queue_set_property_funcs));
>> @@ -644,6 +819,12 @@ static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue
>>  		return exec_queue_user_extensions(xe, q, ext.next_extension,
>>  						  ++ext_number);
>>
>> +	if (xe_exec_queue_is_multi_queue_primary(q)) {
>> +		err = xe_exec_queue_group_init(xe, q);
>> +		if (XE_IOCTL_DBG(xe, err))
>> +			return err;
>> +	}
>> +
>>  	return 0;
>>  }
>>
>> @@ -798,12 +979,18 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
>>  		if (IS_ERR(q))
>>  			return PTR_ERR(q);
>>
>> +		if (xe_exec_queue_is_multi_queue_secondary(q)) {
>> +			err = xe_exec_queue_group_add(xe, q);
>> +			if (XE_IOCTL_DBG(xe, err))
>> +				goto put_exec_queue;
>> +		}
>> +
>>  		if (xe_vm_in_preempt_fence_mode(vm)) {
>>  			q->lr.context = dma_fence_context_alloc(1);
>>
>>  			err = xe_vm_add_compute_exec_queue(vm, q);
>>  			if (XE_IOCTL_DBG(xe, err))
>> -				goto put_exec_queue;
>> +				goto delete_queue_group;
>>  		}
>>
>>  		if (q->vm && q->hwe->hw_engine_group) {
>> @@ -826,6 +1013,9 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
>>
>>  kill_exec_queue:
>>  	xe_exec_queue_kill(q);
>> +delete_queue_group:
>> +	if (xe_exec_queue_is_multi_queue_secondary(q))
>> +		xe_exec_queue_group_delete(xe, q);
>>  put_exec_queue:
>>  	xe_exec_queue_put(q);
>>  	return err;
>> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.h b/drivers/gpu/drm/xe/xe_exec_queue.h
>> index fda4d4f9bda8..e6daa40003f2 100644
>> --- a/drivers/gpu/drm/xe/xe_exec_queue.h
>> +++ b/drivers/gpu/drm/xe/xe_exec_queue.h
>> @@ -66,6 +66,53 @@ static inline bool xe_exec_queue_uses_pxp(struct xe_exec_queue *q)
>>  	return q->pxp.type;
>>  }
>>
>> +/**
>> + * xe_exec_queue_is_multi_queue() - Whether an exec_queue is part of a queue group.
>> + * @q: The exec_queue
>> + *
>> + * Return: True if the exec_queue is part of a queue group, false otherwise.
>> + */
>> +static inline bool xe_exec_queue_is_multi_queue(struct xe_exec_queue *q)
>> +{
>> +	return q->multi_queue.valid;
>> +}
>> +
>> +/**
>> + * xe_exec_queue_is_multi_queue_primary() - Whether an exec_queue is primary queue
>> + * of a multi queue group.
>> + * @q: The exec_queue
>> + *
>> + * Return: True if @q is primary queue of a queue group, false otherwise.
>> + */
>> +static inline bool xe_exec_queue_is_multi_queue_primary(struct xe_exec_queue *q)
>> +{
>> +	return q->multi_queue.is_primary;
>> +}
>> +
>> +/**
>> + * xe_exec_queue_is_multi_queue_secondary() - Whether an exec_queue is secondary queue
>> + * of a multi queue group.
>> + * @q: The exec_queue
>> + *
>> + * Return: True if @q is secondary queue of a queue group, false otherwise.
>> + */
>> +static inline bool xe_exec_queue_is_multi_queue_secondary(struct xe_exec_queue *q)
>> +{
>> +	return xe_exec_queue_is_multi_queue(q) && !xe_exec_queue_is_multi_queue_primary(q);
>> +}
>> +
>> +/**
>> + * xe_exec_queue_multi_queue_primary() - Get multi queue group's primary queue
>> + * @q: The exec_queue
>> + *
>> + * If @q belongs to a multi queue group, then the primary queue of the group will
>> + * be returned. Otherwise, @q will be returned.
>> + */
>> +static inline struct xe_exec_queue *xe_exec_queue_multi_queue_primary(struct xe_exec_queue *q)
>> +{
>> +	return xe_exec_queue_is_multi_queue(q) ? q->multi_queue.group->primary : q;
>> +}
>> +
>>  bool xe_exec_queue_is_lr(struct xe_exec_queue *q);
>>
>>  bool xe_exec_queue_is_idle(struct xe_exec_queue *q);
>> diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> index 771ffe35cd0c..f429b1952be9 100644
>> --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> @@ -32,6 +32,20 @@ enum xe_exec_queue_priority {
>>  	XE_EXEC_QUEUE_PRIORITY_COUNT
>>  };
>>
>> +/**
>> + * struct xe_exec_queue_group - Execution multi queue group
>> + *
>> + * Contains multi queue group information.
>> + */
>> +struct xe_exec_queue_group {
>> +	/** @primary: Primary queue of this group */
>> +	struct xe_exec_queue *primary;
>> +	/** @cgp_bo: BO for the Context Group Page */
>> +	struct xe_bo *cgp_bo;
>> +	/** @xa: xarray to store LRCs */
>> +	struct xarray xa;
>> +};
>> +
>>  /**
>>   * struct xe_exec_queue - Execution queue
>>   *
>> @@ -111,6 +125,18 @@ struct xe_exec_queue {
>>  		struct xe_guc_exec_queue *guc;
>>  	};
>>
>> +	/** @multi_queue: Multi queue information */
>> +	struct {
>> +		/** @multi_queue.group: Queue group information */
>> +		struct xe_exec_queue_group *group;
>> +		/** @multi_queue.pos: Position of queue within the multi-queue group */
>> +		u8 pos;
>> +		/** @multi_queue.valid: Queue belongs to a multi queue group */
>> +		u8 valid:1;
>> +		/** @multi_queue.is_primary: Is primary queue (Q0) of the group */
>> +		u8 is_primary:1;
>> +	} multi_queue;
>> +
>>  	/** @sched_props: scheduling properties */
>>  	struct {
>>  		/** @sched_props.timeslice_us: timeslice period in micro-seconds */
>> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
>> index 47853659a705..4de21e0a4fcf 100644
>> --- a/include/uapi/drm/xe_drm.h
>> +++ b/include/uapi/drm/xe_drm.h
>> @@ -1252,6 +1252,14 @@ struct drm_xe_vm_bind {
>>   *    Given that going into a power-saving state kills PXP HWDRM sessions,
>>   *    runtime PM will be blocked while queues of this type are alive.
>>   *    All PXP queues will be killed if a PXP invalidation event occurs.
>> + *  - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP - Create a multi-queue group
>> + *    or add secondary queues to a multi-queue group.
>> + *    If the extension's 'value' field has %DRM_XE_MULTI_GROUP_CREATE flag set,
>> + *    then a new multi-queue group is created with this queue as the primary queue
>> + *    (Q0). Otherwise, the queue gets added to the multi-queue group whose primary
>> + *    queue's exec_queue_id is specified in the lower 32 bits of the 'value' field.
>> + *    All the other non-relevant bits of extension's 'value' field while adding the
>> + *    primary or the secondary queues of the group must be set to 0.
>>   *
>>   * The example below shows how to use @drm_xe_exec_queue_create to create
>>   * a simple exec_queue (no parallel submission) of class
>> @@ -1292,6 +1300,8 @@ struct drm_xe_exec_queue_create {
>>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY		0
>>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE		1
>>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE		2
>> +#define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP		3
>> +#define     DRM_XE_MULTI_GROUP_CREATE				(1ull << 63)
>>  	/** @extensions: Pointer to the first extension struct, if any */
>>  	__u64 extensions;
>>
>> --
>> 2.43.0
>>

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

* Re: [PATCH v3 09/18] drm/xe/multi_queue: Handle tearing down of a multi queue
  2025-11-21 23:03   ` Matthew Brost
@ 2025-11-22  4:40     ` Niranjana Vishwanathapura
  0 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-22  4:40 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe

On Fri, Nov 21, 2025 at 03:03:36PM -0800, Matthew Brost wrote:
>On Thu, Nov 20, 2025 at 07:51:43PM -0800, Niranjana Vishwanathapura wrote:
>> As all queues of a multi queue group use the primary queue of the group
>> to interface with GuC. Hence there is a dependency between the queues of
>> the group. So, when primary queue of a multi queue group is cleaned up,
>> also trigger a cleanup of the secondary queues also. During cleanup, stop
>> and re-start submission for all queues of a multi queue group to avoid
>> any submission happening in parallel when a queue is being cleaned up.
>>
>> v2: Initialize group->list_lock, add fs_reclaim dependency, remove
>>     unwanted secondary queues cleanup (Matt Brost)
>> v3: Properly handle cleanup of multi-queue group (Matt Brost)
>>
>> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
>> ---
>>  drivers/gpu/drm/xe/xe_exec_queue.c       |  10 ++
>>  drivers/gpu/drm/xe/xe_exec_queue_types.h |   6 +
>>  drivers/gpu/drm/xe/xe_guc_submit.c       | 154 ++++++++++++++++++-----
>>  3 files changed, 142 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
>> index cdc044d3c96c..ab161b74fef0 100644
>> --- a/drivers/gpu/drm/xe/xe_exec_queue.c
>> +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
>> @@ -87,6 +87,7 @@ static void xe_exec_queue_group_cleanup(struct xe_exec_queue *q)
>>  		xe_lrc_put(lrc);
>>
>>  	xa_destroy(&group->xa);
>> +	mutex_destroy(&group->list_lock);
>>  	xe_bo_unpin_map_no_vm(group->cgp_bo);
>>  	kfree(group);
>>  }
>> @@ -627,9 +628,18 @@ static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue *
>>
>>  	group->primary = q;
>>  	group->cgp_bo = bo;
>> +	INIT_LIST_HEAD(&group->list);
>>  	xa_init_flags(&group->xa, XA_FLAGS_ALLOC1);
>> +	mutex_init(&group->list_lock);
>>  	q->multi_queue.group = group;
>>
>> +	/* group->list_lock is used in submission backend */
>> +	if (!IS_ENABLED(CONFIG_LOCKDEP)) {
>
>I believe the polarity is inverted above.
>

Oops. Will fix. Thanks.

Niranjana

>Everything else LGTM.
>
>Matt
>
>> +		fs_reclaim_acquire(GFP_KERNEL);
>> +		might_lock(&group->list_lock);
>> +		fs_reclaim_release(GFP_KERNEL);
>> +	}
>> +
>>  	return 0;
>>  }
>>
>> diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> index cafb3ba9a123..5721fb4bad1a 100644
>> --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> @@ -58,6 +58,10 @@ struct xe_exec_queue_group {
>>  	struct xe_bo *cgp_bo;
>>  	/** @xa: xarray to store LRCs */
>>  	struct xarray xa;
>> +	/** @list: List of all secondary queues in the group */
>> +	struct list_head list;
>> +	/** @list_lock: Secondary queue list lock */
>> +	struct mutex list_lock;
>>  	/** @sync_pending: CGP_SYNC_DONE g2h response pending */
>>  	bool sync_pending;
>>  };
>> @@ -145,6 +149,8 @@ struct xe_exec_queue {
>>  	struct {
>>  		/** @multi_queue.group: Queue group information */
>>  		struct xe_exec_queue_group *group;
>> +		/** @multi_queue.link: Link into group's secondary queues list */
>> +		struct list_head link;
>>  		/** @multi_queue.priority: Queue priority within the multi-queue group */
>>  		enum xe_multi_queue_priority priority;
>>  		/** @multi_queue.pos: Position of queue within the multi-queue group */
>> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
>> index ce870a119800..2e5fff7ad69b 100644
>> --- a/drivers/gpu/drm/xe/xe_guc_submit.c
>> +++ b/drivers/gpu/drm/xe/xe_guc_submit.c
>> @@ -577,6 +577,45 @@ static bool vf_recovery(struct xe_guc *guc)
>>  	return xe_gt_recovery_pending(guc_to_gt(guc));
>>  }
>>
>> +static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
>> +{
>> +	struct xe_guc *guc = exec_queue_to_guc(q);
>> +	struct xe_device *xe = guc_to_xe(guc);
>> +
>> +	/** to wakeup xe_wait_user_fence ioctl if exec queue is reset */
>> +	wake_up_all(&xe->ufence_wq);
>> +
>> +	if (xe_exec_queue_is_lr(q))
>> +		queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr);
>> +	else
>> +		xe_sched_tdr_queue_imm(&q->guc->sched);
>> +}
>> +
>> +static void xe_guc_exec_queue_reset_trigger_cleanup(struct xe_exec_queue *q)
>> +{
>> +	if (xe_exec_queue_is_multi_queue(q)) {
>> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
>> +		struct xe_exec_queue_group *group = q->multi_queue.group;
>> +		struct xe_exec_queue *eq;
>> +
>> +		set_exec_queue_reset(primary);
>> +		if (!exec_queue_banned(primary) && !exec_queue_check_timeout(primary))
>> +			xe_guc_exec_queue_trigger_cleanup(primary);
>> +
>> +		mutex_lock(&group->list_lock);
>> +		list_for_each_entry(eq, &group->list, multi_queue.link) {
>> +			set_exec_queue_reset(eq);
>> +			if (!exec_queue_banned(eq) && !exec_queue_check_timeout(eq))
>> +				xe_guc_exec_queue_trigger_cleanup(eq);
>> +		}
>> +		mutex_unlock(&group->list_lock);
>> +	} else {
>> +		set_exec_queue_reset(q);
>> +		if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
>> +			xe_guc_exec_queue_trigger_cleanup(q);
>> +	}
>> +}
>> +
>>  #define parallel_read(xe_, map_, field_) \
>>  	xe_map_rd_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
>>  			field_)
>> @@ -939,6 +978,50 @@ static void wq_item_append(struct xe_exec_queue *q)
>>  	parallel_write(xe, map, wq_desc.tail, q->guc->wqi_tail);
>>  }
>>
>> +static void xe_guc_exec_queue_submission_start(struct xe_exec_queue *q)
>> +{
>> +	/*
>> +	 * If the exec queue is part of a multi queue group, then start submission
>> +	 * on all queues of the multi queue group.
>> +	 */
>> +	if (xe_exec_queue_is_multi_queue(q)) {
>> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
>> +		struct xe_exec_queue_group *group = q->multi_queue.group;
>> +		struct xe_exec_queue *eq;
>> +
>> +		xe_sched_submission_start(&primary->guc->sched);
>> +
>> +		mutex_lock(&group->list_lock);
>> +		list_for_each_entry(eq, &group->list, multi_queue.link)
>> +			xe_sched_submission_start(&eq->guc->sched);
>> +		mutex_unlock(&group->list_lock);
>> +	} else {
>> +		xe_sched_submission_start(&q->guc->sched);
>> +	}
>> +}
>> +
>> +static void xe_guc_exec_queue_submission_stop(struct xe_exec_queue *q)
>> +{
>> +	/*
>> +	 * If the exec queue is part of a multi queue group, then stop submission
>> +	 * on all queues of the multi queue group.
>> +	 */
>> +	if (xe_exec_queue_is_multi_queue(q)) {
>> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
>> +		struct xe_exec_queue_group *group = q->multi_queue.group;
>> +		struct xe_exec_queue *eq;
>> +
>> +		xe_sched_submission_stop(&primary->guc->sched);
>> +
>> +		mutex_lock(&group->list_lock);
>> +		list_for_each_entry(eq, &group->list, multi_queue.link)
>> +			xe_sched_submission_stop(&eq->guc->sched);
>> +		mutex_unlock(&group->list_lock);
>> +	} else {
>> +		xe_sched_submission_stop(&q->guc->sched);
>> +	}
>> +}
>> +
>>  #define RESUME_PENDING	~0x0ull
>>  static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job)
>>  {
>> @@ -1117,20 +1200,6 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
>>  			       G2H_LEN_DW_DEREGISTER_CONTEXT, 2);
>>  }
>>
>> -static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
>> -{
>> -	struct xe_guc *guc = exec_queue_to_guc(q);
>> -	struct xe_device *xe = guc_to_xe(guc);
>> -
>> -	/** to wakeup xe_wait_user_fence ioctl if exec queue is reset */
>> -	wake_up_all(&xe->ufence_wq);
>> -
>> -	if (xe_exec_queue_is_lr(q))
>> -		queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr);
>> -	else
>> -		xe_sched_tdr_queue_imm(&q->guc->sched);
>> -}
>> -
>>  /**
>>   * xe_guc_submit_wedge() - Wedge GuC submission
>>   * @guc: the GuC object
>> @@ -1204,8 +1273,12 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
>>  	if (!exec_queue_killed(q))
>>  		wedged = guc_submit_hint_wedged(exec_queue_to_guc(q));
>>
>> -	/* Kill the run_job / process_msg entry points */
>> -	xe_sched_submission_stop(sched);
>> +	/*
>> +	 * Kill the run_job / process_msg entry points.
>> +	 * As this function is serialized across exec queues, it is safe to
>> +	 * stop and restart submission on all queues of a multi queue group.
>> +	 */
>> +	xe_guc_exec_queue_submission_stop(q);
>>
>>  	/*
>>  	 * Engine state now mostly stable, disable scheduling / deregister if
>> @@ -1241,7 +1314,7 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
>>  				   q->guc->id);
>>  			xe_devcoredump(q, NULL, "Schedule disable failed to respond, guc_id=%d\n",
>>  				       q->guc->id);
>> -			xe_sched_submission_start(sched);
>> +			xe_guc_exec_queue_submission_start(q);
>>  			xe_gt_reset_async(q->gt);
>>  			return;
>>  		}
>> @@ -1252,7 +1325,7 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
>>
>>  	xe_hw_fence_irq_stop(q->fence_irq);
>>
>> -	xe_sched_submission_start(sched);
>> +	xe_guc_exec_queue_submission_start(q);
>>
>>  	spin_lock(&sched->base.job_list_lock);
>>  	list_for_each_entry(job, &sched->base.pending_list, drm.list)
>> @@ -1410,8 +1483,12 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
>>  	    vf_recovery(guc))
>>  		return DRM_GPU_SCHED_STAT_NO_HANG;
>>
>> -	/* Kill the run_job entry point */
>> -	xe_sched_submission_stop(sched);
>> +	/*
>> +	 * Kill the run_job entry point.
>> +	 * As this function is serialized across exec queues, it is safe to
>> +	 * stop and restart submission on all queues of a multi queue group.
>> +	 */
>> +	xe_guc_exec_queue_submission_stop(q);
>>
>>  	/* Must check all state after stopping scheduler */
>>  	skip_timeout_check = exec_queue_reset(q) ||
>> @@ -1568,7 +1645,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
>>  	 * fences that are complete
>>  	 */
>>  	xe_sched_add_pending_job(sched, job);
>> -	xe_sched_submission_start(sched);
>> +	xe_guc_exec_queue_submission_start(q);
>>
>>  	xe_guc_exec_queue_trigger_cleanup(q);
>>
>> @@ -1592,7 +1669,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
>>  	 * but there is not currently an easy way to do in DRM scheduler. With
>>  	 * some thought, do this in a follow up.
>>  	 */
>> -	xe_sched_submission_start(sched);
>> +	xe_guc_exec_queue_submission_start(q);
>>  handle_vf_resume:
>>  	return DRM_GPU_SCHED_STAT_NO_HANG;
>>  }
>> @@ -1623,6 +1700,14 @@ static void __guc_exec_queue_destroy_async(struct work_struct *w)
>>  	guard(xe_pm_runtime)(guc_to_xe(guc));
>>  	trace_xe_exec_queue_destroy(q);
>>
>> +	if (xe_exec_queue_is_multi_queue_secondary(q)) {
>> +		struct xe_exec_queue_group *group = q->multi_queue.group;
>> +
>> +		mutex_lock(&group->list_lock);
>> +		list_del(&q->multi_queue.link);
>> +		mutex_unlock(&group->list_lock);
>> +	}
>> +
>>  	if (xe_exec_queue_is_lr(q))
>>  		cancel_work_sync(&ge->lr_tdr);
>>  	/* Confirm no work left behind accessing device structures */
>> @@ -1913,6 +1998,19 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
>>
>>  	xe_exec_queue_assign_name(q, q->guc->id);
>>
>> +	/*
>> +	 * Maintain secondary queues of the multi queue group in a list
>> +	 * for handling dependencies across the queues in the group.
>> +	 */
>> +	if (xe_exec_queue_is_multi_queue_secondary(q)) {
>> +		struct xe_exec_queue_group *group = q->multi_queue.group;
>> +
>> +		INIT_LIST_HEAD(&q->multi_queue.link);
>> +		mutex_lock(&group->list_lock);
>> +		list_add_tail(&q->multi_queue.link, &group->list);
>> +		mutex_unlock(&group->list_lock);
>> +	}
>> +
>>  	trace_xe_exec_queue_create(q);
>>
>>  	return 0;
>> @@ -2140,6 +2238,10 @@ static void guc_exec_queue_resume(struct xe_exec_queue *q)
>>
>>  static bool guc_exec_queue_reset_status(struct xe_exec_queue *q)
>>  {
>> +	if (xe_exec_queue_is_multi_queue_secondary(q) &&
>> +	    guc_exec_queue_reset_status(xe_exec_queue_multi_queue_primary(q)))
>> +		return true;
>> +
>>  	return exec_queue_reset(q) || exec_queue_killed_or_banned_or_wedged(q);
>>  }
>>
>> @@ -2801,9 +2903,7 @@ int xe_guc_exec_queue_reset_handler(struct xe_guc *guc, u32 *msg, u32 len)
>>  	 * jobs by setting timeout of the job to the minimum value kicking
>>  	 * guc_exec_queue_timedout_job.
>>  	 */
>> -	set_exec_queue_reset(q);
>> -	if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
>> -		xe_guc_exec_queue_trigger_cleanup(q);
>> +	xe_guc_exec_queue_reset_trigger_cleanup(q);
>>
>>  	return 0;
>>  }
>> @@ -2882,9 +2982,7 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg,
>>  	trace_xe_exec_queue_memory_cat_error(q);
>>
>>  	/* Treat the same as engine reset */
>> -	set_exec_queue_reset(q);
>> -	if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
>> -		xe_guc_exec_queue_trigger_cleanup(q);
>> +	xe_guc_exec_queue_reset_trigger_cleanup(q);
>>
>>  	return 0;
>>  }
>> --
>> 2.43.0
>>

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

* Re: [PATCH v3 09/18] drm/xe/multi_queue: Handle tearing down of a multi queue
  2025-11-21  3:51 ` [PATCH v3 09/18] drm/xe/multi_queue: Handle tearing down of a multi queue Niranjana Vishwanathapura
  2025-11-21 23:03   ` Matthew Brost
@ 2025-11-22  5:47   ` Matthew Brost
  2025-12-09  3:31     ` Niranjana Vishwanathapura
  1 sibling, 1 reply; 41+ messages in thread
From: Matthew Brost @ 2025-11-22  5:47 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

On Thu, Nov 20, 2025 at 07:51:43PM -0800, Niranjana Vishwanathapura wrote:
> As all queues of a multi queue group use the primary queue of the group
> to interface with GuC. Hence there is a dependency between the queues of
> the group. So, when primary queue of a multi queue group is cleaned up,
> also trigger a cleanup of the secondary queues also. During cleanup, stop
> and re-start submission for all queues of a multi queue group to avoid
> any submission happening in parallel when a queue is being cleaned up.
> 
> v2: Initialize group->list_lock, add fs_reclaim dependency, remove
>     unwanted secondary queues cleanup (Matt Brost)
> v3: Properly handle cleanup of multi-queue group (Matt Brost)
> 

Also discussed privately, I believe the agreement is teardown the group
on any individual job's timeout within the group. We maybe can leave
this part out until my series here [1] merges to avoid a conflict with
that series. Not huge deal as this feature won't be enabled for a bit as
all supported platforms are behind force probe.

Matt

[1] https://patchwork.freedesktop.org/series/155314/

> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_exec_queue.c       |  10 ++
>  drivers/gpu/drm/xe/xe_exec_queue_types.h |   6 +
>  drivers/gpu/drm/xe/xe_guc_submit.c       | 154 ++++++++++++++++++-----
>  3 files changed, 142 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
> index cdc044d3c96c..ab161b74fef0 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue.c
> +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
> @@ -87,6 +87,7 @@ static void xe_exec_queue_group_cleanup(struct xe_exec_queue *q)
>  		xe_lrc_put(lrc);
>  
>  	xa_destroy(&group->xa);
> +	mutex_destroy(&group->list_lock);
>  	xe_bo_unpin_map_no_vm(group->cgp_bo);
>  	kfree(group);
>  }
> @@ -627,9 +628,18 @@ static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue *
>  
>  	group->primary = q;
>  	group->cgp_bo = bo;
> +	INIT_LIST_HEAD(&group->list);
>  	xa_init_flags(&group->xa, XA_FLAGS_ALLOC1);
> +	mutex_init(&group->list_lock);
>  	q->multi_queue.group = group;
>  
> +	/* group->list_lock is used in submission backend */
> +	if (!IS_ENABLED(CONFIG_LOCKDEP)) {
> +		fs_reclaim_acquire(GFP_KERNEL);
> +		might_lock(&group->list_lock);
> +		fs_reclaim_release(GFP_KERNEL);
> +	}
> +
>  	return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> index cafb3ba9a123..5721fb4bad1a 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> @@ -58,6 +58,10 @@ struct xe_exec_queue_group {
>  	struct xe_bo *cgp_bo;
>  	/** @xa: xarray to store LRCs */
>  	struct xarray xa;
> +	/** @list: List of all secondary queues in the group */
> +	struct list_head list;
> +	/** @list_lock: Secondary queue list lock */
> +	struct mutex list_lock;
>  	/** @sync_pending: CGP_SYNC_DONE g2h response pending */
>  	bool sync_pending;
>  };
> @@ -145,6 +149,8 @@ struct xe_exec_queue {
>  	struct {
>  		/** @multi_queue.group: Queue group information */
>  		struct xe_exec_queue_group *group;
> +		/** @multi_queue.link: Link into group's secondary queues list */
> +		struct list_head link;
>  		/** @multi_queue.priority: Queue priority within the multi-queue group */
>  		enum xe_multi_queue_priority priority;
>  		/** @multi_queue.pos: Position of queue within the multi-queue group */
> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
> index ce870a119800..2e5fff7ad69b 100644
> --- a/drivers/gpu/drm/xe/xe_guc_submit.c
> +++ b/drivers/gpu/drm/xe/xe_guc_submit.c
> @@ -577,6 +577,45 @@ static bool vf_recovery(struct xe_guc *guc)
>  	return xe_gt_recovery_pending(guc_to_gt(guc));
>  }
>  
> +static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
> +{
> +	struct xe_guc *guc = exec_queue_to_guc(q);
> +	struct xe_device *xe = guc_to_xe(guc);
> +
> +	/** to wakeup xe_wait_user_fence ioctl if exec queue is reset */
> +	wake_up_all(&xe->ufence_wq);
> +
> +	if (xe_exec_queue_is_lr(q))
> +		queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr);
> +	else
> +		xe_sched_tdr_queue_imm(&q->guc->sched);
> +}
> +
> +static void xe_guc_exec_queue_reset_trigger_cleanup(struct xe_exec_queue *q)
> +{
> +	if (xe_exec_queue_is_multi_queue(q)) {
> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
> +		struct xe_exec_queue_group *group = q->multi_queue.group;
> +		struct xe_exec_queue *eq;
> +
> +		set_exec_queue_reset(primary);
> +		if (!exec_queue_banned(primary) && !exec_queue_check_timeout(primary))
> +			xe_guc_exec_queue_trigger_cleanup(primary);
> +
> +		mutex_lock(&group->list_lock);
> +		list_for_each_entry(eq, &group->list, multi_queue.link) {
> +			set_exec_queue_reset(eq);
> +			if (!exec_queue_banned(eq) && !exec_queue_check_timeout(eq))
> +				xe_guc_exec_queue_trigger_cleanup(eq);
> +		}
> +		mutex_unlock(&group->list_lock);
> +	} else {
> +		set_exec_queue_reset(q);
> +		if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
> +			xe_guc_exec_queue_trigger_cleanup(q);
> +	}
> +}
> +
>  #define parallel_read(xe_, map_, field_) \
>  	xe_map_rd_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
>  			field_)
> @@ -939,6 +978,50 @@ static void wq_item_append(struct xe_exec_queue *q)
>  	parallel_write(xe, map, wq_desc.tail, q->guc->wqi_tail);
>  }
>  
> +static void xe_guc_exec_queue_submission_start(struct xe_exec_queue *q)
> +{
> +	/*
> +	 * If the exec queue is part of a multi queue group, then start submission
> +	 * on all queues of the multi queue group.
> +	 */
> +	if (xe_exec_queue_is_multi_queue(q)) {
> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
> +		struct xe_exec_queue_group *group = q->multi_queue.group;
> +		struct xe_exec_queue *eq;
> +
> +		xe_sched_submission_start(&primary->guc->sched);
> +
> +		mutex_lock(&group->list_lock);
> +		list_for_each_entry(eq, &group->list, multi_queue.link)
> +			xe_sched_submission_start(&eq->guc->sched);
> +		mutex_unlock(&group->list_lock);
> +	} else {
> +		xe_sched_submission_start(&q->guc->sched);
> +	}
> +}
> +
> +static void xe_guc_exec_queue_submission_stop(struct xe_exec_queue *q)
> +{
> +	/*
> +	 * If the exec queue is part of a multi queue group, then stop submission
> +	 * on all queues of the multi queue group.
> +	 */
> +	if (xe_exec_queue_is_multi_queue(q)) {
> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
> +		struct xe_exec_queue_group *group = q->multi_queue.group;
> +		struct xe_exec_queue *eq;
> +
> +		xe_sched_submission_stop(&primary->guc->sched);
> +
> +		mutex_lock(&group->list_lock);
> +		list_for_each_entry(eq, &group->list, multi_queue.link)
> +			xe_sched_submission_stop(&eq->guc->sched);
> +		mutex_unlock(&group->list_lock);
> +	} else {
> +		xe_sched_submission_stop(&q->guc->sched);
> +	}
> +}
> +
>  #define RESUME_PENDING	~0x0ull
>  static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job)
>  {
> @@ -1117,20 +1200,6 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
>  			       G2H_LEN_DW_DEREGISTER_CONTEXT, 2);
>  }
>  
> -static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
> -{
> -	struct xe_guc *guc = exec_queue_to_guc(q);
> -	struct xe_device *xe = guc_to_xe(guc);
> -
> -	/** to wakeup xe_wait_user_fence ioctl if exec queue is reset */
> -	wake_up_all(&xe->ufence_wq);
> -
> -	if (xe_exec_queue_is_lr(q))
> -		queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr);
> -	else
> -		xe_sched_tdr_queue_imm(&q->guc->sched);
> -}
> -
>  /**
>   * xe_guc_submit_wedge() - Wedge GuC submission
>   * @guc: the GuC object
> @@ -1204,8 +1273,12 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
>  	if (!exec_queue_killed(q))
>  		wedged = guc_submit_hint_wedged(exec_queue_to_guc(q));
>  
> -	/* Kill the run_job / process_msg entry points */
> -	xe_sched_submission_stop(sched);
> +	/*
> +	 * Kill the run_job / process_msg entry points.
> +	 * As this function is serialized across exec queues, it is safe to
> +	 * stop and restart submission on all queues of a multi queue group.
> +	 */
> +	xe_guc_exec_queue_submission_stop(q);
>  
>  	/*
>  	 * Engine state now mostly stable, disable scheduling / deregister if
> @@ -1241,7 +1314,7 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
>  				   q->guc->id);
>  			xe_devcoredump(q, NULL, "Schedule disable failed to respond, guc_id=%d\n",
>  				       q->guc->id);
> -			xe_sched_submission_start(sched);
> +			xe_guc_exec_queue_submission_start(q);
>  			xe_gt_reset_async(q->gt);
>  			return;
>  		}
> @@ -1252,7 +1325,7 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
>  
>  	xe_hw_fence_irq_stop(q->fence_irq);
>  
> -	xe_sched_submission_start(sched);
> +	xe_guc_exec_queue_submission_start(q);
>  
>  	spin_lock(&sched->base.job_list_lock);
>  	list_for_each_entry(job, &sched->base.pending_list, drm.list)
> @@ -1410,8 +1483,12 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
>  	    vf_recovery(guc))
>  		return DRM_GPU_SCHED_STAT_NO_HANG;
>  
> -	/* Kill the run_job entry point */
> -	xe_sched_submission_stop(sched);
> +	/*
> +	 * Kill the run_job entry point.
> +	 * As this function is serialized across exec queues, it is safe to
> +	 * stop and restart submission on all queues of a multi queue group.
> +	 */
> +	xe_guc_exec_queue_submission_stop(q);
>  
>  	/* Must check all state after stopping scheduler */
>  	skip_timeout_check = exec_queue_reset(q) ||
> @@ -1568,7 +1645,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
>  	 * fences that are complete
>  	 */
>  	xe_sched_add_pending_job(sched, job);
> -	xe_sched_submission_start(sched);
> +	xe_guc_exec_queue_submission_start(q);
>  
>  	xe_guc_exec_queue_trigger_cleanup(q);
>  
> @@ -1592,7 +1669,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
>  	 * but there is not currently an easy way to do in DRM scheduler. With
>  	 * some thought, do this in a follow up.
>  	 */
> -	xe_sched_submission_start(sched);
> +	xe_guc_exec_queue_submission_start(q);
>  handle_vf_resume:
>  	return DRM_GPU_SCHED_STAT_NO_HANG;
>  }
> @@ -1623,6 +1700,14 @@ static void __guc_exec_queue_destroy_async(struct work_struct *w)
>  	guard(xe_pm_runtime)(guc_to_xe(guc));
>  	trace_xe_exec_queue_destroy(q);
>  
> +	if (xe_exec_queue_is_multi_queue_secondary(q)) {
> +		struct xe_exec_queue_group *group = q->multi_queue.group;
> +
> +		mutex_lock(&group->list_lock);
> +		list_del(&q->multi_queue.link);
> +		mutex_unlock(&group->list_lock);
> +	}
> +
>  	if (xe_exec_queue_is_lr(q))
>  		cancel_work_sync(&ge->lr_tdr);
>  	/* Confirm no work left behind accessing device structures */
> @@ -1913,6 +1998,19 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
>  
>  	xe_exec_queue_assign_name(q, q->guc->id);
>  
> +	/*
> +	 * Maintain secondary queues of the multi queue group in a list
> +	 * for handling dependencies across the queues in the group.
> +	 */
> +	if (xe_exec_queue_is_multi_queue_secondary(q)) {
> +		struct xe_exec_queue_group *group = q->multi_queue.group;
> +
> +		INIT_LIST_HEAD(&q->multi_queue.link);
> +		mutex_lock(&group->list_lock);
> +		list_add_tail(&q->multi_queue.link, &group->list);
> +		mutex_unlock(&group->list_lock);
> +	}
> +
>  	trace_xe_exec_queue_create(q);
>  
>  	return 0;
> @@ -2140,6 +2238,10 @@ static void guc_exec_queue_resume(struct xe_exec_queue *q)
>  
>  static bool guc_exec_queue_reset_status(struct xe_exec_queue *q)
>  {
> +	if (xe_exec_queue_is_multi_queue_secondary(q) &&
> +	    guc_exec_queue_reset_status(xe_exec_queue_multi_queue_primary(q)))
> +		return true;
> +
>  	return exec_queue_reset(q) || exec_queue_killed_or_banned_or_wedged(q);
>  }
>  
> @@ -2801,9 +2903,7 @@ int xe_guc_exec_queue_reset_handler(struct xe_guc *guc, u32 *msg, u32 len)
>  	 * jobs by setting timeout of the job to the minimum value kicking
>  	 * guc_exec_queue_timedout_job.
>  	 */
> -	set_exec_queue_reset(q);
> -	if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
> -		xe_guc_exec_queue_trigger_cleanup(q);
> +	xe_guc_exec_queue_reset_trigger_cleanup(q);
>  
>  	return 0;
>  }
> @@ -2882,9 +2982,7 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg,
>  	trace_xe_exec_queue_memory_cat_error(q);
>  
>  	/* Treat the same as engine reset */
> -	set_exec_queue_reset(q);
> -	if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
> -		xe_guc_exec_queue_trigger_cleanup(q);
> +	xe_guc_exec_queue_reset_trigger_cleanup(q);
>  
>  	return 0;
>  }
> -- 
> 2.43.0
> 

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

* Re: [PATCH v3 14/18] drm/xe/multi_queue: Support active group after primary is destroyed
  2025-11-21  3:51 ` [PATCH v3 14/18] drm/xe/multi_queue: Support active group after primary is destroyed Niranjana Vishwanathapura
@ 2025-11-22  5:57   ` Matthew Brost
  2025-11-22  6:08     ` Niranjana Vishwanathapura
  0 siblings, 1 reply; 41+ messages in thread
From: Matthew Brost @ 2025-11-22  5:57 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

On Thu, Nov 20, 2025 at 07:51:48PM -0800, Niranjana Vishwanathapura wrote:
> Add support to keep the group active after the primary queue is
> destroyed. Instead of killing the primary queue during exec_queue
> destroy ioctl, kill it when all the secondary queues of the group
> are killed.
> 
> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_device.c           |  7 ++-
>  drivers/gpu/drm/xe/xe_exec_queue.c       | 55 +++++++++++++++++++++++-
>  drivers/gpu/drm/xe/xe_exec_queue.h       |  2 +
>  drivers/gpu/drm/xe/xe_exec_queue_types.h |  4 ++
>  include/uapi/drm/xe_drm.h                |  4 ++
>  5 files changed, 69 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
> index 037206c8b543..e72294a7d4b1 100644
> --- a/drivers/gpu/drm/xe/xe_device.c
> +++ b/drivers/gpu/drm/xe/xe_device.c
> @@ -177,7 +177,12 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file)
>  	xa_for_each(&xef->exec_queue.xa, idx, q) {
>  		if (q->vm && q->hwe->hw_engine_group)
>  			xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q);
> -		xe_exec_queue_kill(q);
> +
> +		if (xe_exec_queue_is_multi_queue_primary(q))
> +			xe_exec_queue_group_kill_put(q->multi_queue.group);
> +		else
> +			xe_exec_queue_kill(q);
> +
>  		xe_exec_queue_put(q);
>  	}
>  	xa_for_each(&xef->vm.xa, idx, vm)
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
> index ab161b74fef0..839fb08f09e7 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue.c
> +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
> @@ -417,6 +417,26 @@ struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
>  }
>  ALLOW_ERROR_INJECTION(xe_exec_queue_create_bind, ERRNO);
>  
> +static void xe_exec_queue_group_kill(struct kref *ref)
> +{
> +	struct xe_exec_queue_group *group = container_of(ref, struct xe_exec_queue_group,
> +							 kill_refcount);
> +	xe_exec_queue_kill(group->primary);
> +}
> +
> +static inline void xe_exec_queue_group_kill_get(struct xe_exec_queue_group *group)
> +{
> +	kref_get(&group->kill_refcount);
> +}
> +
> +void xe_exec_queue_group_kill_put(struct xe_exec_queue_group *group)
> +{
> +	if (!group)
> +		return;
> +
> +	kref_put(&group->kill_refcount, xe_exec_queue_group_kill);
> +}
> +
>  void xe_exec_queue_destroy(struct kref *ref)
>  {
>  	struct xe_exec_queue *q = container_of(ref, struct xe_exec_queue, refcount);
> @@ -629,6 +649,7 @@ static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue *
>  	group->primary = q;
>  	group->cgp_bo = bo;
>  	INIT_LIST_HEAD(&group->list);
> +	kref_init(&group->kill_refcount);
>  	xa_init_flags(&group->xa, XA_FLAGS_ALLOC1);
>  	mutex_init(&group->list_lock);
>  	q->multi_queue.group = group;
> @@ -704,6 +725,11 @@ static int xe_exec_queue_group_add(struct xe_device *xe, struct xe_exec_queue *q
>  
>  	q->multi_queue.pos = pos;
>  
> +	if (group->primary->multi_queue.keep_active) {
> +		xe_exec_queue_group_kill_get(group);
> +		q->multi_queue.keep_active = true;
> +	}
> +
>  	return 0;
>  }
>  
> @@ -717,6 +743,11 @@ static void xe_exec_queue_group_delete(struct xe_device *xe, struct xe_exec_queu
>  	lrc = xa_erase(&group->xa, q->multi_queue.pos);
>  	xe_assert(xe, lrc);
>  	xe_lrc_put(lrc);
> +
> +	if (q->multi_queue.keep_active) {
> +		xe_exec_queue_group_kill_put(group);
> +		q->multi_queue.keep_active = false;
> +	}
>  }
>  
>  static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue *q,
> @@ -735,12 +766,24 @@ static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue
>  		return -EINVAL;
>  
>  	if (value & DRM_XE_MULTI_GROUP_CREATE) {
> -		if (XE_IOCTL_DBG(xe, value & ~DRM_XE_MULTI_GROUP_CREATE))
> +		if (XE_IOCTL_DBG(xe, value & ~(DRM_XE_MULTI_GROUP_CREATE |
> +					       DRM_XE_MULTI_GROUP_KEEP_ACTIVE)))
> +			return -EINVAL;
> +
> +		/*
> +		 * KEEP_ACTIVE is not supported in preempt fence mode as in that mode,
> +		 * VM_DESTROY ioctl expects all exec queues of that VM are already killed.
> +		 */

Is the compute UMD ok with this? I really hope by the time multi-queue
is enabled in the KMD the compute UMD is only using faulting VMs. Not
blocker, we likely could actually fix preempt fence mode to avoid this
restriction, more something we need communicate to the UMDs teams / keep
an on eye if this becomes an issue.

Anyways patch LGTM:

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> +		if (XE_IOCTL_DBG(xe, (value & DRM_XE_MULTI_GROUP_KEEP_ACTIVE) &&
> +				 xe_vm_in_preempt_fence_mode(q->vm)))
>  			return -EINVAL;
>  
>  		q->multi_queue.valid = true;
>  		q->multi_queue.is_primary = true;
>  		q->multi_queue.pos = 0;
> +		if (value & DRM_XE_MULTI_GROUP_KEEP_ACTIVE)
> +			q->multi_queue.keep_active = true;
> +
>  		return 0;
>  	}
>  
> @@ -1286,6 +1329,11 @@ void xe_exec_queue_kill(struct xe_exec_queue *q)
>  
>  	q->ops->kill(q);
>  	xe_vm_remove_compute_exec_queue(q->vm, q);
> +
> +	if (!xe_exec_queue_is_multi_queue_primary(q) && q->multi_queue.keep_active) {
> +		xe_exec_queue_group_kill_put(q->multi_queue.group);
> +		q->multi_queue.keep_active = false;
> +	}
>  }
>  
>  int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data,
> @@ -1312,7 +1360,10 @@ int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data,
>  	if (q->vm && q->hwe->hw_engine_group)
>  		xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q);
>  
> -	xe_exec_queue_kill(q);
> +	if (xe_exec_queue_is_multi_queue_primary(q))
> +		xe_exec_queue_group_kill_put(q->multi_queue.group);
> +	else
> +		xe_exec_queue_kill(q);
>  
>  	trace_xe_exec_queue_close(q);
>  	xe_exec_queue_put(q);
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.h b/drivers/gpu/drm/xe/xe_exec_queue.h
> index ffcc1feb879e..10abed98fb6b 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue.h
> +++ b/drivers/gpu/drm/xe/xe_exec_queue.h
> @@ -113,6 +113,8 @@ static inline struct xe_exec_queue *xe_exec_queue_multi_queue_primary(struct xe_
>  	return xe_exec_queue_is_multi_queue(q) ? q->multi_queue.group->primary : q;
>  }
>  
> +void xe_exec_queue_group_kill_put(struct xe_exec_queue_group *group);
> +
>  bool xe_exec_queue_is_lr(struct xe_exec_queue *q);
>  
>  bool xe_exec_queue_is_idle(struct xe_exec_queue *q);
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> index 5721fb4bad1a..c6b80977ff4f 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> @@ -62,6 +62,8 @@ struct xe_exec_queue_group {
>  	struct list_head list;
>  	/** @list_lock: Secondary queue list lock */
>  	struct mutex list_lock;
> +	/** @kill_refcount: ref count to kill primary queue */
> +	struct kref kill_refcount;
>  	/** @sync_pending: CGP_SYNC_DONE g2h response pending */
>  	bool sync_pending;
>  };
> @@ -159,6 +161,8 @@ struct xe_exec_queue {
>  		u8 valid:1;
>  		/** @multi_queue.is_primary: Is primary queue (Q0) of the group */
>  		u8 is_primary:1;
> +		/** @multi_queue.keep_active: Keep the group active after primary is destroyed */
> +		u8 keep_active:1;
>  	} multi_queue;
>  
>  	/** @sched_props: scheduling properties */
> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> index 71a851615876..74cbebb24aa5 100644
> --- a/include/uapi/drm/xe_drm.h
> +++ b/include/uapi/drm/xe_drm.h
> @@ -1260,6 +1260,9 @@ struct drm_xe_vm_bind {
>   *    then a new multi-queue group is created with this queue as the primary queue
>   *    (Q0). Otherwise, the queue gets added to the multi-queue group whose primary
>   *    queue's exec_queue_id is specified in the lower 32 bits of the 'value' field.
> + *    If the extension's 'value' field has %DRM_XE_MULTI_GROUP_KEEP_ACTIVE flag
> + *    set, then the multi-queue group is kept active after the primary queue is
> + *    destroyed.
>   *    All the other non-relevant bits of extension's 'value' field while adding the
>   *    primary or the secondary queues of the group must be set to 0.
>   *  - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY - Set the queue
> @@ -1307,6 +1310,7 @@ struct drm_xe_exec_queue_create {
>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE		2
>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP		3
>  #define     DRM_XE_MULTI_GROUP_CREATE				(1ull << 63)
> +#define     DRM_XE_MULTI_GROUP_KEEP_ACTIVE			(1ull << 62)
>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY	4
>  	/** @extensions: Pointer to the first extension struct, if any */
>  	__u64 extensions;
> -- 
> 2.43.0
> 

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

* Re: [PATCH v3 16/18] drm/xe/doc: Add documentation for Multi Queue Group
  2025-11-21  3:51 ` [PATCH v3 16/18] drm/xe/doc: Add documentation for Multi Queue Group Niranjana Vishwanathapura
@ 2025-11-22  6:02   ` Matthew Brost
  0 siblings, 0 replies; 41+ messages in thread
From: Matthew Brost @ 2025-11-22  6:02 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

On Thu, Nov 20, 2025 at 07:51:50PM -0800, Niranjana Vishwanathapura wrote:
> Add kernel documentation for Multi Queue group and update
> the corresponding rst.
> 
> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> ---
>  Documentation/gpu/xe/xe_exec_queue.rst |  6 ++++
>  drivers/gpu/drm/xe/xe_exec_queue.c     | 45 ++++++++++++++++++++++++++
>  2 files changed, 51 insertions(+)
> 
> diff --git a/Documentation/gpu/xe/xe_exec_queue.rst b/Documentation/gpu/xe/xe_exec_queue.rst
> index 6076569e311c..732af4741df4 100644
> --- a/Documentation/gpu/xe/xe_exec_queue.rst
> +++ b/Documentation/gpu/xe/xe_exec_queue.rst
> @@ -7,6 +7,12 @@ Execution Queue
>  .. kernel-doc:: drivers/gpu/drm/xe/xe_exec_queue.c
>     :doc: Execution Queue
>  
> +Multi Queue Group
> +=================
> +
> +.. kernel-doc:: drivers/gpu/drm/xe/xe_exec_queue.c
> +   :doc: Multi Queue Group
> +
>  Internal API
>  ============
>  
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
> index 839fb08f09e7..50326b4431e0 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue.c
> +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
> @@ -54,6 +54,51 @@
>   * the ring operations the different engine classes support.
>   */
>  
> +/**
> + * DOC: Multi Queue Group
> + *
> + * Multi Queue Group is another mode of execution supported by the compute
> + * and blitter copy command streamers (CCS and BCS, respectively). It is
> + * an enhancement of the existing hardware architecture and leverages the
> + * same submission model. It enables support for efficient, parallel
> + * execution of multiple queues within a single shared context. The multi
> + * queue group functionality is only supported with GuC submission backend.
> + * All the queues of a group must use the same address space (VM).
> + *
> + * The DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE execution queue property
> + * supports creating a multi queue group and adding queues to a queue group.
> + *
> + * The XE_EXEC_QUEUE_CREATE ioctl call with above property with value field
> + * set to DRM_XE_MULTI_GROUP_CREATE, will create a new multi queue group with
> + * the queue being created as the primary queue (aka q0) of the group. To add
> + * secondary queues to the group, they need to be created with the above
> + * property with id of the primary queue as the value. The properties of
> + * the primary queue (like priority, time slice) applies to the whole group.
> + * So, these properties can't be set for secondary queues of a group.
> + *
> + * The hardware does not support removing a queue from a multi-queue group.
> + * However, queues can be dynamically added to the group. A group can have
> + * up to 64 queues. To support this, XeKMD holds references to LRCs of the
> + * queues even after the queues are destroyed by the user until the whole
> + * group is destroyed. The secondary queues hold a reference to the primary
> + * queue thus preventing the group from being destroyed when user destroys
> + * the primary queue. Once the primary queue is destroyed, secondary queues
> + * can't be added to the queue group, but they can continue to submit the
> + * jobs if the DRM_XE_MULTI_GROUP_KEEP_ACTIVE flag is set during the multi
> + * queue group creation.
> + *
> + * The queues of a multi queue group can set their priority within the group
> + * through the DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY property.
> + * This multi queue priority can also be set dynamically through the
> + * XE_EXEC_QUEUE_SET_PROPERTY ioctl. This is the only other property
> + * supported by the secondary queues of a multi queue group, other than
> + * DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE.
> + *
> + * When GuC reports an error on any of the queues of a multi queue group,
> + * the queue cleanup mechanism is invoked for all the queues of the group
> + * as hardware cannot make progress on the multi queue context.
> + */
> +
>  enum xe_exec_queue_sched_prop {
>  	XE_EXEC_QUEUE_JOB_TIMEOUT = 0,
>  	XE_EXEC_QUEUE_TIMESLICE = 1,
> -- 
> 2.43.0
> 

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

* Re: [PATCH v3 14/18] drm/xe/multi_queue: Support active group after primary is destroyed
  2025-11-22  5:57   ` Matthew Brost
@ 2025-11-22  6:08     ` Niranjana Vishwanathapura
  0 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-11-22  6:08 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe

On Fri, Nov 21, 2025 at 09:57:11PM -0800, Matthew Brost wrote:
>On Thu, Nov 20, 2025 at 07:51:48PM -0800, Niranjana Vishwanathapura wrote:
>> Add support to keep the group active after the primary queue is
>> destroyed. Instead of killing the primary queue during exec_queue
>> destroy ioctl, kill it when all the secondary queues of the group
>> are killed.
>>
>> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
>> ---
>>  drivers/gpu/drm/xe/xe_device.c           |  7 ++-
>>  drivers/gpu/drm/xe/xe_exec_queue.c       | 55 +++++++++++++++++++++++-
>>  drivers/gpu/drm/xe/xe_exec_queue.h       |  2 +
>>  drivers/gpu/drm/xe/xe_exec_queue_types.h |  4 ++
>>  include/uapi/drm/xe_drm.h                |  4 ++
>>  5 files changed, 69 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
>> index 037206c8b543..e72294a7d4b1 100644
>> --- a/drivers/gpu/drm/xe/xe_device.c
>> +++ b/drivers/gpu/drm/xe/xe_device.c
>> @@ -177,7 +177,12 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file)
>>  	xa_for_each(&xef->exec_queue.xa, idx, q) {
>>  		if (q->vm && q->hwe->hw_engine_group)
>>  			xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q);
>> -		xe_exec_queue_kill(q);
>> +
>> +		if (xe_exec_queue_is_multi_queue_primary(q))
>> +			xe_exec_queue_group_kill_put(q->multi_queue.group);
>> +		else
>> +			xe_exec_queue_kill(q);
>> +
>>  		xe_exec_queue_put(q);
>>  	}
>>  	xa_for_each(&xef->vm.xa, idx, vm)
>> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
>> index ab161b74fef0..839fb08f09e7 100644
>> --- a/drivers/gpu/drm/xe/xe_exec_queue.c
>> +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
>> @@ -417,6 +417,26 @@ struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
>>  }
>>  ALLOW_ERROR_INJECTION(xe_exec_queue_create_bind, ERRNO);
>>
>> +static void xe_exec_queue_group_kill(struct kref *ref)
>> +{
>> +	struct xe_exec_queue_group *group = container_of(ref, struct xe_exec_queue_group,
>> +							 kill_refcount);
>> +	xe_exec_queue_kill(group->primary);
>> +}
>> +
>> +static inline void xe_exec_queue_group_kill_get(struct xe_exec_queue_group *group)
>> +{
>> +	kref_get(&group->kill_refcount);
>> +}
>> +
>> +void xe_exec_queue_group_kill_put(struct xe_exec_queue_group *group)
>> +{
>> +	if (!group)
>> +		return;
>> +
>> +	kref_put(&group->kill_refcount, xe_exec_queue_group_kill);
>> +}
>> +
>>  void xe_exec_queue_destroy(struct kref *ref)
>>  {
>>  	struct xe_exec_queue *q = container_of(ref, struct xe_exec_queue, refcount);
>> @@ -629,6 +649,7 @@ static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue *
>>  	group->primary = q;
>>  	group->cgp_bo = bo;
>>  	INIT_LIST_HEAD(&group->list);
>> +	kref_init(&group->kill_refcount);
>>  	xa_init_flags(&group->xa, XA_FLAGS_ALLOC1);
>>  	mutex_init(&group->list_lock);
>>  	q->multi_queue.group = group;
>> @@ -704,6 +725,11 @@ static int xe_exec_queue_group_add(struct xe_device *xe, struct xe_exec_queue *q
>>
>>  	q->multi_queue.pos = pos;
>>
>> +	if (group->primary->multi_queue.keep_active) {
>> +		xe_exec_queue_group_kill_get(group);
>> +		q->multi_queue.keep_active = true;
>> +	}
>> +
>>  	return 0;
>>  }
>>
>> @@ -717,6 +743,11 @@ static void xe_exec_queue_group_delete(struct xe_device *xe, struct xe_exec_queu
>>  	lrc = xa_erase(&group->xa, q->multi_queue.pos);
>>  	xe_assert(xe, lrc);
>>  	xe_lrc_put(lrc);
>> +
>> +	if (q->multi_queue.keep_active) {
>> +		xe_exec_queue_group_kill_put(group);
>> +		q->multi_queue.keep_active = false;
>> +	}
>>  }
>>
>>  static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue *q,
>> @@ -735,12 +766,24 @@ static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue
>>  		return -EINVAL;
>>
>>  	if (value & DRM_XE_MULTI_GROUP_CREATE) {
>> -		if (XE_IOCTL_DBG(xe, value & ~DRM_XE_MULTI_GROUP_CREATE))
>> +		if (XE_IOCTL_DBG(xe, value & ~(DRM_XE_MULTI_GROUP_CREATE |
>> +					       DRM_XE_MULTI_GROUP_KEEP_ACTIVE)))
>> +			return -EINVAL;
>> +
>> +		/*
>> +		 * KEEP_ACTIVE is not supported in preempt fence mode as in that mode,
>> +		 * VM_DESTROY ioctl expects all exec queues of that VM are already killed.
>> +		 */
>
>Is the compute UMD ok with this? I really hope by the time multi-queue
>is enabled in the KMD the compute UMD is only using faulting VMs. Not
>blocker, we likely could actually fix preempt fence mode to avoid this
>restriction, more something we need communicate to the UMDs teams / keep
>an on eye if this becomes an issue.
>

Yes, compute team is fine with using the fault mode.

Niranjana

>Anyways patch LGTM:
>
>Reviewed-by: Matthew Brost <matthew.brost@intel.com>
>
>> +		if (XE_IOCTL_DBG(xe, (value & DRM_XE_MULTI_GROUP_KEEP_ACTIVE) &&
>> +				 xe_vm_in_preempt_fence_mode(q->vm)))
>>  			return -EINVAL;
>>
>>  		q->multi_queue.valid = true;
>>  		q->multi_queue.is_primary = true;
>>  		q->multi_queue.pos = 0;
>> +		if (value & DRM_XE_MULTI_GROUP_KEEP_ACTIVE)
>> +			q->multi_queue.keep_active = true;
>> +
>>  		return 0;
>>  	}
>>
>> @@ -1286,6 +1329,11 @@ void xe_exec_queue_kill(struct xe_exec_queue *q)
>>
>>  	q->ops->kill(q);
>>  	xe_vm_remove_compute_exec_queue(q->vm, q);
>> +
>> +	if (!xe_exec_queue_is_multi_queue_primary(q) && q->multi_queue.keep_active) {
>> +		xe_exec_queue_group_kill_put(q->multi_queue.group);
>> +		q->multi_queue.keep_active = false;
>> +	}
>>  }
>>
>>  int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data,
>> @@ -1312,7 +1360,10 @@ int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data,
>>  	if (q->vm && q->hwe->hw_engine_group)
>>  		xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q);
>>
>> -	xe_exec_queue_kill(q);
>> +	if (xe_exec_queue_is_multi_queue_primary(q))
>> +		xe_exec_queue_group_kill_put(q->multi_queue.group);
>> +	else
>> +		xe_exec_queue_kill(q);
>>
>>  	trace_xe_exec_queue_close(q);
>>  	xe_exec_queue_put(q);
>> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.h b/drivers/gpu/drm/xe/xe_exec_queue.h
>> index ffcc1feb879e..10abed98fb6b 100644
>> --- a/drivers/gpu/drm/xe/xe_exec_queue.h
>> +++ b/drivers/gpu/drm/xe/xe_exec_queue.h
>> @@ -113,6 +113,8 @@ static inline struct xe_exec_queue *xe_exec_queue_multi_queue_primary(struct xe_
>>  	return xe_exec_queue_is_multi_queue(q) ? q->multi_queue.group->primary : q;
>>  }
>>
>> +void xe_exec_queue_group_kill_put(struct xe_exec_queue_group *group);
>> +
>>  bool xe_exec_queue_is_lr(struct xe_exec_queue *q);
>>
>>  bool xe_exec_queue_is_idle(struct xe_exec_queue *q);
>> diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> index 5721fb4bad1a..c6b80977ff4f 100644
>> --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> @@ -62,6 +62,8 @@ struct xe_exec_queue_group {
>>  	struct list_head list;
>>  	/** @list_lock: Secondary queue list lock */
>>  	struct mutex list_lock;
>> +	/** @kill_refcount: ref count to kill primary queue */
>> +	struct kref kill_refcount;
>>  	/** @sync_pending: CGP_SYNC_DONE g2h response pending */
>>  	bool sync_pending;
>>  };
>> @@ -159,6 +161,8 @@ struct xe_exec_queue {
>>  		u8 valid:1;
>>  		/** @multi_queue.is_primary: Is primary queue (Q0) of the group */
>>  		u8 is_primary:1;
>> +		/** @multi_queue.keep_active: Keep the group active after primary is destroyed */
>> +		u8 keep_active:1;
>>  	} multi_queue;
>>
>>  	/** @sched_props: scheduling properties */
>> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
>> index 71a851615876..74cbebb24aa5 100644
>> --- a/include/uapi/drm/xe_drm.h
>> +++ b/include/uapi/drm/xe_drm.h
>> @@ -1260,6 +1260,9 @@ struct drm_xe_vm_bind {
>>   *    then a new multi-queue group is created with this queue as the primary queue
>>   *    (Q0). Otherwise, the queue gets added to the multi-queue group whose primary
>>   *    queue's exec_queue_id is specified in the lower 32 bits of the 'value' field.
>> + *    If the extension's 'value' field has %DRM_XE_MULTI_GROUP_KEEP_ACTIVE flag
>> + *    set, then the multi-queue group is kept active after the primary queue is
>> + *    destroyed.
>>   *    All the other non-relevant bits of extension's 'value' field while adding the
>>   *    primary or the secondary queues of the group must be set to 0.
>>   *  - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY - Set the queue
>> @@ -1307,6 +1310,7 @@ struct drm_xe_exec_queue_create {
>>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE		2
>>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP		3
>>  #define     DRM_XE_MULTI_GROUP_CREATE				(1ull << 63)
>> +#define     DRM_XE_MULTI_GROUP_KEEP_ACTIVE			(1ull << 62)
>>  #define   DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY	4
>>  	/** @extensions: Pointer to the first extension struct, if any */
>>  	__u64 extensions;
>> --
>> 2.43.0
>>

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

* Re: [PATCH v3 17/18] drm/xe/doc: Add documentation for Multi Queue Group GuC interface
  2025-11-21  3:51 ` [PATCH v3 17/18] drm/xe/doc: Add documentation for Multi Queue Group GuC interface Niranjana Vishwanathapura
@ 2025-11-22  6:10   ` Matthew Brost
  0 siblings, 0 replies; 41+ messages in thread
From: Matthew Brost @ 2025-11-22  6:10 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

On Thu, Nov 20, 2025 at 07:51:51PM -0800, Niranjana Vishwanathapura wrote:
> Add kernel documentation for Multi Queue group GuC interface.
> 
> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> ---
>  Documentation/gpu/xe/xe_exec_queue.rst |  8 ++++
>  drivers/gpu/drm/xe/xe_exec_queue.c     |  3 ++
>  drivers/gpu/drm/xe/xe_guc_submit.c     | 57 ++++++++++++++++++++++++++
>  3 files changed, 68 insertions(+)
> 
> diff --git a/Documentation/gpu/xe/xe_exec_queue.rst b/Documentation/gpu/xe/xe_exec_queue.rst
> index 732af4741df4..8707806211c9 100644
> --- a/Documentation/gpu/xe/xe_exec_queue.rst
> +++ b/Documentation/gpu/xe/xe_exec_queue.rst
> @@ -13,6 +13,14 @@ Multi Queue Group
>  .. kernel-doc:: drivers/gpu/drm/xe/xe_exec_queue.c
>     :doc: Multi Queue Group
>  
> +.. _multi-queue-group-guc-interface:
> +
> +Multi Queue Group GuC interface
> +===============================
> +
> +.. kernel-doc:: drivers/gpu/drm/xe/xe_guc_submit.c
> +   :doc: Multi Queue Group GuC interface
> +
>  Internal API
>  ============
>  
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
> index 50326b4431e0..387497dfd5b1 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue.c
> +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
> @@ -97,6 +97,9 @@
>   * When GuC reports an error on any of the queues of a multi queue group,
>   * the queue cleanup mechanism is invoked for all the queues of the group
>   * as hardware cannot make progress on the multi queue context.
> + *
> + * Refer :ref:`multi-queue-group-guc-interface` for multi queue group GuC
> + * interface.
>   */
>  
>  enum xe_exec_queue_sched_prop {
> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
> index fbe3de30af60..86946760ad0f 100644
> --- a/drivers/gpu/drm/xe/xe_guc_submit.c
> +++ b/drivers/gpu/drm/xe/xe_guc_submit.c
> @@ -659,6 +659,63 @@ static void set_exec_queue_group_banned(struct xe_exec_queue *q)
>  	xe_map_wr_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
>  			field_, val_)
>  
> +/**
> + * DOC: Multi Queue Group GuC interface
> + *
> + * The multi queue group coordination between KMD and GuC is through a software
> + * construct called Context Group Page (CGP). The CGP is a KMD managed 4KB page
> + * allocated in the global GTT.
> + *
> + * CGP format:
> + *
> + * +-----------+---------------------------+---------------------------------------------+
> + * | DWORD     | Name                      | Description                                 |
> + * +-----------+---------------------------+---------------------------------------------+
> + * | 0         | Version                   | Bits [15:8]=Major ver, [7:0]=Minor ver      |
> + * +-----------+---------------------------+---------------------------------------------+
> + * | 1..15     | RESERVED                  | MBZ                                         |
> + * +-----------+---------------------------+---------------------------------------------+
> + * | 16        | KMD_QUEUE_UPDATE_MASK_DW0 | KMD queue mask for queues 31..0             |
> + * +-----------+---------------------------+---------------------------------------------+
> + * | 17        | KMD_QUEUE_UPDATE_MASK_DW1 | KMD queue mask for queues 63..32            |
> + * +-----------+---------------------------+---------------------------------------------+
> + * | 18..31    | RESERVED                  | MBZ                                         |
> + * +-----------+---------------------------+---------------------------------------------+
> + * | 32        | Q0CD_DW0                  | Queue 0 context LRC descriptor lower DWORD  |
> + * +-----------+---------------------------+---------------------------------------------+
> + * | 33        | Q0ContextIndex            | Context ID for Queue 0                      |
> + * +-----------+---------------------------+---------------------------------------------+
> + * | 34        | Q1CD_DW0                  | Queue 1 context LRC descriptor lower DWORD  |
> + * +-----------+---------------------------+---------------------------------------------+
> + * | 35        | Q1ContextIndex            | Context ID for Queue 1                      |
> + * +-----------+---------------------------+---------------------------------------------+
> + * | ...       |...                        | ...                                         |
> + * +-----------+---------------------------+---------------------------------------------+
> + * | 158       | Q63CD_DW0                 | Queue 63 context LRC descriptor lower DWORD |
> + * +-----------+---------------------------+---------------------------------------------+
> + * | 159       | Q63ContextIndex           | Context ID for Queue 63                     |
> + * +-----------+---------------------------+---------------------------------------------+
> + * | 160..1024 | RESERVED                  | MBZ                                         |
> + * +-----------+---------------------------+---------------------------------------------+
> + *
> + * While registering Q0 with GuC, CGP is updated with Q0 entry and GuC is notified
> + * through XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE H2G message which specifies
> + * the CGP address. When the secondary queues are added to the group, the CGP is
> + * updated with entry for that queue and GuC is notified through the H2G interface
> + * XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC. GuC responds to these H2G messages
> + * with a XE_GUC_ACTION_NOTIFY_MULTIQ_CONTEXT_CGP_SYNC_DONE G2H message. GuC also
> + * sends a XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CGP_CONTEXT_ERROR notification for any
> + * error in the CGP. Only one of these CGP update messages can be outstanding
> + * (waiting for GuC response) at any time. The bits in KMD_QUEUE_UPDATE_MASK_DW*
> + * fields indicate which queue entry is being updated in the CGP.
> + *
> + * The primary queue (Q0) represents the multi queue group context in GuC and
> + * submission on any queue of the group must be through Q0 GuC interface only.
> + *
> + * As it is not required to register secondary queues with GuC, the secondary queue
> + * context ids in the CGP are populated with Q0 context id.
> + */
> +
>  #define CGP_VERSION_MAJOR_SHIFT	8
>  
>  static void xe_guc_exec_queue_group_cgp_update(struct xe_device *xe,
> -- 
> 2.43.0
> 

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

* Re: [PATCH v3 03/18] drm/xe/multi_queue: Add GuC interface for multi queue support
  2025-11-21  3:51 ` [PATCH v3 03/18] drm/xe/multi_queue: Add GuC " Niranjana Vishwanathapura
@ 2025-11-22 22:16   ` Matthew Brost
  2025-12-03  3:40     ` Niranjana Vishwanathapura
  0 siblings, 1 reply; 41+ messages in thread
From: Matthew Brost @ 2025-11-22 22:16 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

On Thu, Nov 20, 2025 at 07:51:37PM -0800, Niranjana Vishwanathapura wrote:
> Implement GuC commands and response along with the Context
> Group Page (CGP) interface for multi queue support.
> 
> Ensure that only primary queue (q0) of a multi queue group
> communicate with GuC. The secondary queues of the group only
> need to maintain LRCA and interface with drm scheduler.
> 
> Use primary queue's submit_wq for all secondary queues of a multi
> queue group. This serialization avoids any locking around CGP
> synchronization with GuC.
> 
> v2: Fix G2H_LEN_DW_MULTI_QUEUE_CONTEXT value, add more comments
>     (Matt Brost)
> v3: Minor code refactro, use xe_gt_assert
> 
> Signed-off-by: Stuart Summers <stuart.summers@intel.com>
> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
> ---
>  drivers/gpu/drm/xe/abi/guc_actions_abi.h |   3 +
>  drivers/gpu/drm/xe/xe_exec_queue_types.h |   2 +
>  drivers/gpu/drm/xe/xe_guc_ct.c           |   4 +
>  drivers/gpu/drm/xe/xe_guc_fwif.h         |   3 +
>  drivers/gpu/drm/xe/xe_guc_submit.c       | 276 +++++++++++++++++++++--
>  drivers/gpu/drm/xe/xe_guc_submit.h       |   1 +
>  6 files changed, 267 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/abi/guc_actions_abi.h b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
> index 47756e4674a1..3e9fbed9cda6 100644
> --- a/drivers/gpu/drm/xe/abi/guc_actions_abi.h
> +++ b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
> @@ -139,6 +139,9 @@ enum xe_guc_action {
>  	XE_GUC_ACTION_DEREGISTER_G2G = 0x4508,
>  	XE_GUC_ACTION_DEREGISTER_CONTEXT_DONE = 0x4600,
>  	XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC = 0x4601,
> +	XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE = 0x4602,
> +	XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC = 0x4603,
> +	XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE = 0x4604,
>  	XE_GUC_ACTION_CLIENT_SOFT_RESET = 0x5507,
>  	XE_GUC_ACTION_SET_ENG_UTIL_BUFF = 0x550A,
>  	XE_GUC_ACTION_SET_DEVICE_ENGINE_ACTIVITY_BUFFER = 0x550C,
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> index f429b1952be9..b9da51ab7eaf 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> @@ -44,6 +44,8 @@ struct xe_exec_queue_group {
>  	struct xe_bo *cgp_bo;
>  	/** @xa: xarray to store LRCs */
>  	struct xarray xa;
> +	/** @sync_pending: CGP_SYNC_DONE g2h response pending */
> +	bool sync_pending;
>  };
>  
>  /**
> diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c
> index 2697d711adb2..43a79bcdfb18 100644
> --- a/drivers/gpu/drm/xe/xe_guc_ct.c
> +++ b/drivers/gpu/drm/xe/xe_guc_ct.c
> @@ -1307,6 +1307,7 @@ static int parse_g2h_event(struct xe_guc_ct *ct, u32 *msg, u32 len)
>  	lockdep_assert_held(&ct->lock);
>  
>  	switch (action) {
> +	case XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE:
>  	case XE_GUC_ACTION_SCHED_CONTEXT_MODE_DONE:
>  	case XE_GUC_ACTION_DEREGISTER_CONTEXT_DONE:
>  	case XE_GUC_ACTION_SCHED_ENGINE_MODE_DONE:
> @@ -1569,6 +1570,9 @@ static int process_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len)
>  		ret = xe_guc_g2g_test_notification(guc, payload, adj_len);
>  		break;
>  #endif
> +	case XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE:
> +		ret = xe_guc_exec_queue_cgp_sync_done_handler(guc, payload, adj_len);
> +		break;
>  	default:
>  		xe_gt_err(gt, "unexpected G2H action 0x%04x\n", action);
>  	}
> diff --git a/drivers/gpu/drm/xe/xe_guc_fwif.h b/drivers/gpu/drm/xe/xe_guc_fwif.h
> index c90dd266e9cf..9b090d9b95f1 100644
> --- a/drivers/gpu/drm/xe/xe_guc_fwif.h
> +++ b/drivers/gpu/drm/xe/xe_guc_fwif.h
> @@ -16,6 +16,7 @@
>  #define G2H_LEN_DW_DEREGISTER_CONTEXT		3
>  #define G2H_LEN_DW_TLB_INVALIDATE		3
>  #define G2H_LEN_DW_G2G_NOTIFY_MIN		3
> +#define G2H_LEN_DW_MULTI_QUEUE_CONTEXT		3
>  
>  #define GUC_ID_MAX			65535
>  #define GUC_ID_UNKNOWN			0xffffffff
> @@ -62,6 +63,8 @@ struct guc_ctxt_registration_info {
>  	u32 wq_base_lo;
>  	u32 wq_base_hi;
>  	u32 wq_size;
> +	u32 cgp_lo;
> +	u32 cgp_hi;
>  	u32 hwlrca_lo;
>  	u32 hwlrca_hi;
>  };
> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
> index 7e0882074a99..c68739fd7592 100644
> --- a/drivers/gpu/drm/xe/xe_guc_submit.c
> +++ b/drivers/gpu/drm/xe/xe_guc_submit.c
> @@ -19,6 +19,7 @@
>  #include "abi/guc_klvs_abi.h"
>  #include "regs/xe_lrc_layout.h"
>  #include "xe_assert.h"
> +#include "xe_bo.h"
>  #include "xe_devcoredump.h"
>  #include "xe_device.h"
>  #include "xe_exec_queue.h"
> @@ -541,7 +542,8 @@ static void init_policies(struct xe_guc *guc, struct xe_exec_queue *q)
>  	u32 slpc_exec_queue_freq_req = 0;
>  	u32 preempt_timeout_us = q->sched_props.preempt_timeout_us;
>  
> -	xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q));
> +	xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q) &&
> +		     !xe_exec_queue_is_multi_queue_secondary(q));
>  
>  	if (q->flags & EXEC_QUEUE_FLAG_LOW_LATENCY)
>  		slpc_exec_queue_freq_req |= SLPC_CTX_FREQ_REQ_IS_COMPUTE;
> @@ -561,6 +563,8 @@ static void set_min_preemption_timeout(struct xe_guc *guc, struct xe_exec_queue
>  {
>  	struct exec_queue_policy policy;
>  
> +	xe_assert(guc_to_xe(guc), !xe_exec_queue_is_multi_queue_secondary(q));
> +
>  	__guc_exec_queue_policy_start_klv(&policy, q->guc->id);
>  	__guc_exec_queue_policy_add_preemption_timeout(&policy, 1);
>  
> @@ -568,6 +572,11 @@ static void set_min_preemption_timeout(struct xe_guc *guc, struct xe_exec_queue
>  		       __guc_exec_queue_policy_action_size(&policy), 0, 0);
>  }
>  
> +static bool vf_recovery(struct xe_guc *guc)
> +{
> +	return xe_gt_recovery_pending(guc_to_gt(guc));
> +}
> +
>  #define parallel_read(xe_, map_, field_) \
>  	xe_map_rd_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
>  			field_)
> @@ -575,6 +584,117 @@ static void set_min_preemption_timeout(struct xe_guc *guc, struct xe_exec_queue
>  	xe_map_wr_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
>  			field_, val_)
>  
> +#define CGP_VERSION_MAJOR_SHIFT	8
> +
> +static void xe_guc_exec_queue_group_cgp_update(struct xe_device *xe,
> +					       struct xe_exec_queue *q)
> +{
> +	struct xe_exec_queue_group *group = q->multi_queue.group;
> +	u32 guc_id = group->primary->guc->id;
> +
> +	/* Currently implementing CGP version 1.0 */
> +	xe_map_wr(xe, &group->cgp_bo->vmap, 0, u32,
> +		  1 << CGP_VERSION_MAJOR_SHIFT);
> +
> +	xe_map_wr(xe, &group->cgp_bo->vmap,
> +		  (32 + q->multi_queue.pos * 2) * sizeof(u32),
> +		  u32, lower_32_bits(xe_lrc_descriptor(q->lrc[0])));
> +
> +	xe_map_wr(xe, &group->cgp_bo->vmap,
> +		  (33 + q->multi_queue.pos * 2) * sizeof(u32),
> +		  u32, guc_id);
> +
> +	if (q->multi_queue.pos / 32) {
> +		xe_map_wr(xe, &group->cgp_bo->vmap, 17 * sizeof(u32),
> +			  u32, BIT(q->multi_queue.pos % 32));
> +		xe_map_wr(xe, &group->cgp_bo->vmap, 16 * sizeof(u32), u32, 0);
> +	} else {
> +		xe_map_wr(xe, &group->cgp_bo->vmap, 16 * sizeof(u32),
> +			  u32, BIT(q->multi_queue.pos));
> +		xe_map_wr(xe, &group->cgp_bo->vmap, 17 * sizeof(u32), u32, 0);
> +	}
> +}
> +
> +static void xe_guc_exec_queue_group_cgp_sync(struct xe_guc *guc,
> +					     struct xe_exec_queue *q,
> +					     const u32 *action, u32 len)
> +{
> +	struct xe_exec_queue_group *group = q->multi_queue.group;
> +	struct xe_device *xe = guc_to_xe(guc);
> +	long ret;
> +
> +	/*
> +	 * As all queues of a multi queue group use single drm scheduler
> +	 * submit workqueue, CGP synchronization with GuC are serialized.
> +	 * Hence, no locking is required here.
> +	 * Wait for any pending CGP_SYNC_DONE response before updating the
> +	 * CGP page and sending CGP_SYNC message.
> +	 */
> +	ret = wait_event_timeout(guc->ct.wq,
> +				 !READ_ONCE(group->sync_pending) ||
> +				 xe_guc_read_stopped(guc), HZ);
> +	if ((!ret && !vf_recovery(guc)) || xe_guc_read_stopped(guc)) {

As this series isn't quite right for VF migration, I'd leave out any VF
migration changes. However I'd add a "FIXME: VF migration" in a follow
up + maybe open a Jira to track. I'd like to VF migration working for
multi-queue by the time we remove force probe for a device with
multi-queue, so have a bit of time and we discuss further on how to make
this work but I think it shouldn't be too bad.

> +		xe_gt_warn(guc_to_gt(guc), "Wait for CGP_SYNC_DONE response failed!\n");
> +		return;
> +	}
> +
> +	xe_guc_exec_queue_group_cgp_update(xe, q);
> +
> +	WRITE_ONCE(group->sync_pending, true);
> +	xe_guc_ct_send(&guc->ct, action, len, G2H_LEN_DW_MULTI_QUEUE_CONTEXT, 1);
> +}
> +
> +static void __register_exec_queue_group(struct xe_guc *guc,
> +					struct xe_exec_queue *q,
> +					struct guc_ctxt_registration_info *info)
> +{
> +#define MAX_MULTI_QUEUE_REG_SIZE	(8)
> +	u32 action[MAX_MULTI_QUEUE_REG_SIZE];
> +	int len = 0;
> +
> +	action[len++] = XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE;
> +	action[len++] = info->flags;
> +	action[len++] = info->context_idx;
> +	action[len++] = info->engine_class;
> +	action[len++] = info->engine_submit_mask;
> +	action[len++] = 0; /* Reserved */
> +	action[len++] = info->cgp_lo;
> +	action[len++] = info->cgp_hi;
> +
> +	xe_gt_assert(guc_to_gt(guc), len <= MAX_MULTI_QUEUE_REG_SIZE);
> +#undef MAX_MULTI_QUEUE_REG_SIZE
> +
> +	/*
> +	 * The above XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE do expect a
> +	 * XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE response
> +	 * from guc.
> +	 */
> +	xe_guc_exec_queue_group_cgp_sync(guc, q, action, len);
> +}
> +
> +static void xe_guc_exec_queue_group_add(struct xe_guc *guc,
> +					struct xe_exec_queue *q)
> +{
> +#define MAX_MULTI_QUEUE_CGP_SYNC_SIZE  (2)
> +	u32 action[MAX_MULTI_QUEUE_CGP_SYNC_SIZE];
> +	int len = 0;
> +
> +	xe_gt_assert(guc_to_gt(guc), xe_exec_queue_is_multi_queue_secondary(q));
> +
> +	action[len++] = XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC;
> +	action[len++] = q->multi_queue.group->primary->guc->id;
> +
> +	xe_gt_assert(guc_to_gt(guc), len <= MAX_MULTI_QUEUE_CGP_SYNC_SIZE);
> +#undef MAX_MULTI_QUEUE_CGP_SYNC_SIZE
> +
> +	/*
> +	 * The above XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC do expect a
> +	 * XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE response
> +	 * from guc.
> +	 */
> +	xe_guc_exec_queue_group_cgp_sync(guc, q, action, len);
> +}
> +
>  static void __register_mlrc_exec_queue(struct xe_guc *guc,
>  				       struct xe_exec_queue *q,
>  				       struct guc_ctxt_registration_info *info)
> @@ -670,6 +790,13 @@ static void register_exec_queue(struct xe_exec_queue *q, int ctx_type)
>  	info.flags = CONTEXT_REGISTRATION_FLAG_KMD |
>  		FIELD_PREP(CONTEXT_REGISTRATION_FLAG_TYPE, ctx_type);
>  
> +	if (xe_exec_queue_is_multi_queue(q)) {
> +		struct xe_exec_queue_group *group = q->multi_queue.group;
> +
> +		info.cgp_lo = xe_bo_ggtt_addr(group->cgp_bo);
> +		info.cgp_hi = 0;
> +	}
> +
>  	if (xe_exec_queue_is_parallel(q)) {
>  		u64 ggtt_addr = xe_lrc_parallel_ggtt_addr(lrc);
>  		struct iosys_map map = xe_lrc_parallel_map(lrc);
> @@ -700,11 +827,18 @@ static void register_exec_queue(struct xe_exec_queue *q, int ctx_type)
>  
>  	set_exec_queue_registered(q);
>  	trace_xe_exec_queue_register(q);
> -	if (xe_exec_queue_is_parallel(q))
> +	if (xe_exec_queue_is_multi_queue_primary(q))
> +		__register_exec_queue_group(guc, q, &info);
> +	else if (xe_exec_queue_is_parallel(q))
>  		__register_mlrc_exec_queue(guc, q, &info);
> -	else
> +	else if (!xe_exec_queue_is_multi_queue_secondary(q))
>  		__register_exec_queue(guc, &info);
> -	init_policies(guc, q);
> +
> +	if (!xe_exec_queue_is_multi_queue_secondary(q))
> +		init_policies(guc, q);
> +
> +	if (xe_exec_queue_is_multi_queue_secondary(q))
> +		xe_guc_exec_queue_group_add(guc, q);
>  }
>  
>  static u32 wq_space_until_wrap(struct xe_exec_queue *q)
> @@ -712,11 +846,6 @@ static u32 wq_space_until_wrap(struct xe_exec_queue *q)
>  	return (WQ_SIZE - q->guc->wqi_tail);
>  }
>  
> -static bool vf_recovery(struct xe_guc *guc)
> -{
> -	return xe_gt_recovery_pending(guc_to_gt(guc));
> -}
> -
>  static int wq_wait_for_space(struct xe_exec_queue *q, u32 wqi_size)
>  {
>  	struct xe_guc *guc = exec_queue_to_guc(q);
> @@ -833,6 +962,12 @@ static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job)
>  	if (exec_queue_suspended(q) && !xe_exec_queue_is_parallel(q))
>  		return;
>  
> +	/*
> +	 * All queues in a multi-queue group will use the primary queue
> +	 * of the group to interface with GuC.
> +	 */
> +	q = xe_exec_queue_multi_queue_primary(q);
> +
>  	if (!exec_queue_enabled(q) && !exec_queue_suspended(q)) {
>  		action[len++] = XE_GUC_ACTION_SCHED_CONTEXT_MODE_SET;
>  		action[len++] = q->guc->id;
> @@ -879,6 +1014,18 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job)
>  	trace_xe_sched_job_run(job);
>  
>  	if (!killed_or_banned_or_wedged && !xe_sched_job_is_error(job)) {
> +		if (xe_exec_queue_is_multi_queue_secondary(q)) {
> +			struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
> +
> +			if (exec_queue_killed_or_banned_or_wedged(primary)) {
> +				killed_or_banned_or_wedged = true;
> +				goto run_job_out;
> +			}
> +
> +			if (!exec_queue_registered(primary))
> +				register_exec_queue(primary, GUC_CONTEXT_NORMAL);
> +		}
> +
>  		if (!exec_queue_registered(q))
>  			register_exec_queue(q, GUC_CONTEXT_NORMAL);
>  		if (!job->skip_emit)
> @@ -887,6 +1034,7 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job)
>  		job->skip_emit = false;
>  	}
>  
> +run_job_out:
>  	/*
>  	 * We don't care about job-fence ordering in LR VMs because these fences
>  	 * are never exported; they are used solely to keep jobs on the pending
> @@ -912,6 +1060,11 @@ int xe_guc_read_stopped(struct xe_guc *guc)
>  	return atomic_read(&guc->submission_state.stopped);
>  }
>  
> +static void handle_multi_queue_secondary_sched_done(struct xe_guc *guc,
> +						    struct xe_exec_queue *q,
> +						    u32 runnable_state);
> +static void handle_deregister_done(struct xe_guc *guc, struct xe_exec_queue *q);
> +
>  #define MAKE_SCHED_CONTEXT_ACTION(q, enable_disable)			\
>  	u32 action[] = {						\
>  		XE_GUC_ACTION_SCHED_CONTEXT_MODE_SET,			\
> @@ -925,7 +1078,9 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
>  	MAKE_SCHED_CONTEXT_ACTION(q, DISABLE);
>  	int ret;
>  
> -	set_min_preemption_timeout(guc, q);
> +	if (!xe_exec_queue_is_multi_queue_secondary(q))
> +		set_min_preemption_timeout(guc, q);
> +
>  	smp_rmb();
>  	ret = wait_event_timeout(guc->ct.wq,
>  				 (!exec_queue_pending_enable(q) &&
> @@ -953,9 +1108,12 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
>  	 * Reserve space for both G2H here as the 2nd G2H is sent from a G2H
>  	 * handler and we are not allowed to reserved G2H space in handlers.
>  	 */
> -	xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
> -		       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET +
> -		       G2H_LEN_DW_DEREGISTER_CONTEXT, 2);
> +	if (xe_exec_queue_is_multi_queue_secondary(q))
> +		handle_multi_queue_secondary_sched_done(guc, q, 0);
> +	else
> +		xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
> +			       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET +
> +			       G2H_LEN_DW_DEREGISTER_CONTEXT, 2);
>  }
>  
>  static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
> @@ -1161,8 +1319,11 @@ static void enable_scheduling(struct xe_exec_queue *q)
>  	set_exec_queue_enabled(q);
>  	trace_xe_exec_queue_scheduling_enable(q);
>  
> -	xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
> -		       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
> +	if (xe_exec_queue_is_multi_queue_secondary(q))
> +		handle_multi_queue_secondary_sched_done(guc, q, 1);
> +	else
> +		xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
> +			       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
>  
>  	ret = wait_event_timeout(guc->ct.wq,
>  				 !exec_queue_pending_enable(q) ||
> @@ -1186,14 +1347,17 @@ static void disable_scheduling(struct xe_exec_queue *q, bool immediate)
>  	xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q));
>  	xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_disable(q));
>  
> -	if (immediate)
> +	if (immediate && !xe_exec_queue_is_multi_queue_secondary(q))
>  		set_min_preemption_timeout(guc, q);
>  	clear_exec_queue_enabled(q);
>  	set_exec_queue_pending_disable(q);
>  	trace_xe_exec_queue_scheduling_disable(q);
>  
> -	xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
> -		       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
> +	if (xe_exec_queue_is_multi_queue_secondary(q))
> +		handle_multi_queue_secondary_sched_done(guc, q, 0);
> +	else
> +		xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
> +			       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
>  }
>  
>  static void __deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q)
> @@ -1211,8 +1375,11 @@ static void __deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q)
>  	set_exec_queue_destroyed(q);
>  	trace_xe_exec_queue_deregister(q);
>  
> -	xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
> -		       G2H_LEN_DW_DEREGISTER_CONTEXT, 1);
> +	if (xe_exec_queue_is_multi_queue_secondary(q))
> +		handle_deregister_done(guc, q);
> +	else
> +		xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
> +			       G2H_LEN_DW_DEREGISTER_CONTEXT, 1);
>  }
>  
>  static enum drm_gpu_sched_stat
> @@ -1655,6 +1822,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
>  {
>  	struct xe_gpu_scheduler *sched;
>  	struct xe_guc *guc = exec_queue_to_guc(q);
> +	struct workqueue_struct *submit_wq = NULL;
>  	struct xe_guc_exec_queue *ge;
>  	long timeout;
>  	int err, i;
> @@ -1675,8 +1843,20 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
>  
>  	timeout = (q->vm && xe_vm_in_lr_mode(q->vm)) ? MAX_SCHEDULE_TIMEOUT :
>  		  msecs_to_jiffies(q->sched_props.job_timeout_ms);
> +
> +	/*
> +	 * Use primary queue's submit_wq for all secondary queues of a
> +	 * multi queue group. This serialization avoids any locking around
> +	 * CGP synchronization with GuC.
> +	 */
> +	if (xe_exec_queue_is_multi_queue_secondary(q)) {
> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
> +
> +		submit_wq = primary->guc->sched.base.submit_wq;
> +	}
> +
>  	err = xe_sched_init(&ge->sched, &drm_sched_ops, &xe_sched_ops,
> -			    NULL, xe_lrc_ring_size() / MAX_JOB_SIZE_BYTES, 64,
> +			    submit_wq, xe_lrc_ring_size() / MAX_JOB_SIZE_BYTES, 64,
>  			    timeout, guc_to_gt(guc)->ordered_wq, NULL,
>  			    q->name, gt_to_xe(q->gt)->drm.dev);
>  	if (err)
> @@ -2413,7 +2593,11 @@ static void deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q)
>  
>  	trace_xe_exec_queue_deregister(q);
>  
> -	xe_guc_ct_send_g2h_handler(&guc->ct, action, ARRAY_SIZE(action));
> +	if (xe_exec_queue_is_multi_queue_secondary(q))
> +		handle_deregister_done(guc, q);
> +	else
> +		xe_guc_ct_send_g2h_handler(&guc->ct, action,
> +					   ARRAY_SIZE(action));
>  }
>  
>  static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q,
> @@ -2463,6 +2647,16 @@ static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q,
>  	}
>  }
>  
> +static void handle_multi_queue_secondary_sched_done(struct xe_guc *guc,
> +						    struct xe_exec_queue *q,
> +						    u32 runnable_state)
> +{
> +	/* Take CT lock here as handle_sched_done() do send a h2g message */
> +	mutex_lock(&guc->ct.lock);
> +	handle_sched_done(guc, q, runnable_state);
> +	mutex_unlock(&guc->ct.lock);
> +}
> +
>  int xe_guc_sched_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
>  {
>  	struct xe_exec_queue *q;
> @@ -2667,6 +2861,44 @@ int xe_guc_exec_queue_reset_failure_handler(struct xe_guc *guc, u32 *msg, u32 le
>  	return 0;
>  }
>  
> +/**
> + * xe_guc_exec_queue_cgp_sync_done_handler - CGP synchronization done handler
> + * @guc: guc
> + * @msg: message indicating CGP sync done
> + * @len: length of message
> + *
> + * Set multi queue group's sync_pending flag to false and wakeup anyone waiting
> + * for CGP synchronization to complete.
> + *
> + * Return: 0 on success, -EPROTO for malformed messages.
> + */
> +int xe_guc_exec_queue_cgp_sync_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
> +{
> +	struct xe_device *xe = guc_to_xe(guc);
> +	struct xe_exec_queue *q;
> +	u32 guc_id = msg[0];
> +
> +	if (unlikely(len < 1)) {
> +		drm_err(&xe->drm, "Invalid CGP_SYNC_DONE length %u", len);
> +		return -EPROTO;
> +	}
> +
> +	q = g2h_exec_queue_lookup(guc, guc_id);
> +	if (unlikely(!q))
> +		return -EPROTO;
> +
> +	if (!xe_exec_queue_is_multi_queue_primary(q)) {
> +		drm_err(&xe->drm, "Unexpected CGP_SYNC_DONE response");
> +		return -EPROTO;
> +	}
> +
> +	/* Wakeup the serialized cgp update wait */
> +	WRITE_ONCE(q->multi_queue.group->sync_pending, false);
> +	wake_up_all(&guc->ct.wq);

We have helper for this now: xe_guc_ct_wake_waiters

Still need to scrub the entire code for 'wake_up_all(&guc->ct.wq)' and
fix those up but let's use this in new code.

Other than these mirror nit, lgtm.

Matt

> +
> +	return 0;
> +}
> +
>  static void
>  guc_exec_queue_wq_snapshot_capture(struct xe_exec_queue *q,
>  				   struct xe_guc_submit_exec_queue_snapshot *snapshot)
> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.h b/drivers/gpu/drm/xe/xe_guc_submit.h
> index b49a2748ec46..abfa94bce391 100644
> --- a/drivers/gpu/drm/xe/xe_guc_submit.h
> +++ b/drivers/gpu/drm/xe/xe_guc_submit.h
> @@ -34,6 +34,7 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg,
>  					       u32 len);
>  int xe_guc_exec_queue_reset_failure_handler(struct xe_guc *guc, u32 *msg, u32 len);
>  int xe_guc_error_capture_handler(struct xe_guc *guc, u32 *msg, u32 len);
> +int xe_guc_exec_queue_cgp_sync_done_handler(struct xe_guc *guc, u32 *msg, u32 len);
>  
>  struct xe_guc_submit_exec_queue_snapshot *
>  xe_guc_exec_queue_snapshot_capture(struct xe_exec_queue *q);
> -- 
> 2.43.0
> 

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

* ✗ Xe.CI.Full: failure for drm/xe: Multi Queue feature support (rev3)
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (21 preceding siblings ...)
  2025-11-21  8:10 ` ✗ Xe.CI.Full: " Patchwork
@ 2025-11-24 14:04 ` Patchwork
  2025-11-27  9:38 ` [PATCH v3 00/18] drm/xe: Multi Queue feature support Hoppe, Mateusz
  23 siblings, 0 replies; 41+ messages in thread
From: Patchwork @ 2025-11-24 14:04 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe

[-- Attachment #1: Type: text/plain, Size: 19596 bytes --]

== Series Details ==

Series: drm/xe: Multi Queue feature support (rev3)
URL   : https://patchwork.freedesktop.org/series/156865/
State : failure

== Summary ==

CI Bug Log - changes from xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7_FULL -> xe-pw-156865v3_FULL
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with xe-pw-156865v3_FULL absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in xe-pw-156865v3_FULL, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Participating hosts (4 -> 4)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in xe-pw-156865v3_FULL:

### IGT changes ###

#### Possible regressions ####

  * igt@xe_exec_queue_property@invalid-property:
    - shard-dg2-set2:     [PASS][1] -> [FAIL][2]
   [1]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-dg2-466/igt@xe_exec_queue_property@invalid-property.html
   [2]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-466/igt@xe_exec_queue_property@invalid-property.html
    - shard-lnl:          [PASS][3] -> [FAIL][4]
   [3]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-lnl-3/igt@xe_exec_queue_property@invalid-property.html
   [4]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-lnl-3/igt@xe_exec_queue_property@invalid-property.html
    - shard-adlp:         [PASS][5] -> [FAIL][6]
   [5]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-adlp-4/igt@xe_exec_queue_property@invalid-property.html
   [6]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-3/igt@xe_exec_queue_property@invalid-property.html

  
Known issues
------------

  Here are the changes found in xe-pw-156865v3_FULL that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@kms_big_fb@x-tiled-32bpp-rotate-270:
    - shard-dg2-set2:     NOTRUN -> [SKIP][7] ([Intel XE#316])
   [7]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_big_fb@x-tiled-32bpp-rotate-270.html

  * igt@kms_big_fb@yf-tiled-32bpp-rotate-90:
    - shard-dg2-set2:     NOTRUN -> [SKIP][8] ([Intel XE#1124])
   [8]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_big_fb@yf-tiled-32bpp-rotate-90.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180:
    - shard-adlp:         NOTRUN -> [SKIP][9] ([Intel XE#1124])
   [9]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180.html

  * igt@kms_bw@connected-linear-tiling-3-displays-2560x1440p:
    - shard-adlp:         NOTRUN -> [SKIP][10] ([Intel XE#2191])
   [10]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_bw@connected-linear-tiling-3-displays-2560x1440p.html

  * igt@kms_bw@linear-tiling-3-displays-1920x1080p:
    - shard-dg2-set2:     NOTRUN -> [SKIP][11] ([Intel XE#367])
   [11]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_bw@linear-tiling-3-displays-1920x1080p.html

  * igt@kms_bw@linear-tiling-4-displays-3840x2160p:
    - shard-adlp:         NOTRUN -> [SKIP][12] ([Intel XE#367])
   [12]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_bw@linear-tiling-4-displays-3840x2160p.html

  * igt@kms_ccs@bad-aux-stride-4-tiled-mtl-rc-ccs-cc:
    - shard-dg2-set2:     NOTRUN -> [SKIP][13] ([Intel XE#455] / [Intel XE#787]) +1 other test skip
   [13]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_ccs@bad-aux-stride-4-tiled-mtl-rc-ccs-cc.html

  * igt@kms_ccs@bad-aux-stride-4-tiled-mtl-rc-ccs-cc@pipe-c-dp-4:
    - shard-dg2-set2:     NOTRUN -> [SKIP][14] ([Intel XE#787]) +6 other tests skip
   [14]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_ccs@bad-aux-stride-4-tiled-mtl-rc-ccs-cc@pipe-c-dp-4.html

  * igt@kms_ccs@crc-primary-basic-4-tiled-mtl-rc-ccs:
    - shard-adlp:         NOTRUN -> [SKIP][15] ([Intel XE#455] / [Intel XE#787]) +1 other test skip
   [15]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_ccs@crc-primary-basic-4-tiled-mtl-rc-ccs.html

  * igt@kms_ccs@crc-primary-basic-4-tiled-mtl-rc-ccs@pipe-c-hdmi-a-1:
    - shard-adlp:         NOTRUN -> [SKIP][16] ([Intel XE#787]) +2 other tests skip
   [16]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_ccs@crc-primary-basic-4-tiled-mtl-rc-ccs@pipe-c-hdmi-a-1.html

  * igt@kms_ccs@crc-sprite-planes-basic-4-tiled-bmg-ccs:
    - shard-adlp:         NOTRUN -> [SKIP][17] ([Intel XE#2907])
   [17]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_ccs@crc-sprite-planes-basic-4-tiled-bmg-ccs.html

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs@pipe-b-hdmi-a-6:
    - shard-dg2-set2:     [PASS][18] -> [INCOMPLETE][19] ([Intel XE#1727] / [Intel XE#3113] / [Intel XE#4345] / [Intel XE#6168])
   [18]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-dg2-464/igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs@pipe-b-hdmi-a-6.html
   [19]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-435/igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs@pipe-b-hdmi-a-6.html

  * igt@kms_chamelium_edid@dp-edid-change-during-hibernate:
    - shard-dg2-set2:     NOTRUN -> [SKIP][20] ([Intel XE#373])
   [20]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_chamelium_edid@dp-edid-change-during-hibernate.html

  * igt@kms_color@ctm-blue-to-red:
    - shard-adlp:         NOTRUN -> [DMESG-WARN][21] ([Intel XE#2953] / [Intel XE#4173]) +1 other test dmesg-warn
   [21]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_color@ctm-blue-to-red.html

  * igt@kms_cursor_crc@cursor-random-32x10:
    - shard-dg2-set2:     NOTRUN -> [SKIP][22] ([Intel XE#455])
   [22]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_cursor_crc@cursor-random-32x10.html

  * igt@kms_cursor_legacy@2x-nonblocking-modeset-vs-cursor-atomic:
    - shard-adlp:         NOTRUN -> [SKIP][23] ([Intel XE#309])
   [23]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_cursor_legacy@2x-nonblocking-modeset-vs-cursor-atomic.html

  * igt@kms_flip@flip-vs-suspend@b-hdmi-a1:
    - shard-adlp:         [PASS][24] -> [DMESG-WARN][25] ([Intel XE#2953] / [Intel XE#4173]) +2 other tests dmesg-warn
   [24]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-adlp-9/igt@kms_flip@flip-vs-suspend@b-hdmi-a1.html
   [25]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_flip@flip-vs-suspend@b-hdmi-a1.html

  * igt@kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-render:
    - shard-dg2-set2:     NOTRUN -> [SKIP][26] ([Intel XE#651])
   [26]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-indfb-pgflip-blt:
    - shard-adlp:         NOTRUN -> [SKIP][27] ([Intel XE#656])
   [27]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-indfb-pgflip-blt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-blt:
    - shard-dg2-set2:     NOTRUN -> [SKIP][28] ([Intel XE#653]) +1 other test skip
   [28]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-blt.html

  * igt@kms_pm_rpm@dpms-non-lpsp:
    - shard-adlp:         NOTRUN -> [SKIP][29] ([Intel XE#836])
   [29]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@kms_pm_rpm@dpms-non-lpsp.html

  * igt@kms_psr2_sf@fbc-psr2-overlay-plane-update-sf-dmg-area:
    - shard-dg2-set2:     NOTRUN -> [SKIP][30] ([Intel XE#1406] / [Intel XE#1489])
   [30]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_psr2_sf@fbc-psr2-overlay-plane-update-sf-dmg-area.html

  * igt@kms_psr@fbc-psr2-primary-blt:
    - shard-dg2-set2:     NOTRUN -> [SKIP][31] ([Intel XE#1406] / [Intel XE#2850] / [Intel XE#929])
   [31]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_psr@fbc-psr2-primary-blt.html

  * igt@xe_eudebug@vm-bind-clear-faultable:
    - shard-dg2-set2:     NOTRUN -> [SKIP][32] ([Intel XE#4837]) +1 other test skip
   [32]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_eudebug@vm-bind-clear-faultable.html

  * igt@xe_exec_basic@multigpu-many-execqueues-many-vm-rebind:
    - shard-adlp:         NOTRUN -> [SKIP][33] ([Intel XE#1392] / [Intel XE#5575])
   [33]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@xe_exec_basic@multigpu-many-execqueues-many-vm-rebind.html

  * igt@xe_exec_fault_mode@once-userptr-prefetch:
    - shard-adlp:         NOTRUN -> [SKIP][34] ([Intel XE#288] / [Intel XE#5561]) +1 other test skip
   [34]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@xe_exec_fault_mode@once-userptr-prefetch.html

  * igt@xe_exec_fault_mode@twice-bindexecqueue-userptr-rebind-prefetch:
    - shard-dg2-set2:     NOTRUN -> [SKIP][35] ([Intel XE#288]) +2 other tests skip
   [35]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_exec_fault_mode@twice-bindexecqueue-userptr-rebind-prefetch.html

  * igt@xe_exec_system_allocator@process-many-large-execqueues-mmap-free:
    - shard-dg2-set2:     NOTRUN -> [SKIP][36] ([Intel XE#4915]) +36 other tests skip
   [36]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_exec_system_allocator@process-many-large-execqueues-mmap-free.html

  * igt@xe_exec_system_allocator@process-many-large-new-bo-map-nomemset:
    - shard-adlp:         NOTRUN -> [SKIP][37] ([Intel XE#4915]) +10 other tests skip
   [37]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-8/igt@xe_exec_system_allocator@process-many-large-new-bo-map-nomemset.html

  * igt@xe_oa@create-destroy-userspace-config:
    - shard-dg2-set2:     NOTRUN -> [SKIP][38] ([Intel XE#3573]) +1 other test skip
   [38]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_oa@create-destroy-userspace-config.html

  * igt@xe_pm@s2idle-d3cold-basic-exec:
    - shard-dg2-set2:     NOTRUN -> [SKIP][39] ([Intel XE#2284] / [Intel XE#366])
   [39]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_pm@s2idle-d3cold-basic-exec.html

  * igt@xe_pmu@engine-activity-accuracy-90@engine-drm_xe_engine_class_copy0:
    - shard-lnl:          [PASS][40] -> [FAIL][41] ([Intel XE#6251]) +1 other test fail
   [40]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-lnl-1/igt@xe_pmu@engine-activity-accuracy-90@engine-drm_xe_engine_class_copy0.html
   [41]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-lnl-4/igt@xe_pmu@engine-activity-accuracy-90@engine-drm_xe_engine_class_copy0.html

  * igt@xe_pxp@pxp-stale-queue-post-suspend:
    - shard-dg2-set2:     NOTRUN -> [SKIP][42] ([Intel XE#4733])
   [42]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_pxp@pxp-stale-queue-post-suspend.html

  * igt@xe_query@multigpu-query-oa-units:
    - shard-dg2-set2:     NOTRUN -> [SKIP][43] ([Intel XE#944])
   [43]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@xe_query@multigpu-query-oa-units.html

  
#### Possible fixes ####

  * igt@kms_async_flips@async-flip-with-page-flip-events-linear-atomic@pipe-c-edp-1:
    - shard-lnl:          [FAIL][44] ([Intel XE#6054]) -> [PASS][45] +3 other tests pass
   [44]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-lnl-4/igt@kms_async_flips@async-flip-with-page-flip-events-linear-atomic@pipe-c-edp-1.html
   [45]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-lnl-5/igt@kms_async_flips@async-flip-with-page-flip-events-linear-atomic@pipe-c-edp-1.html

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc:
    - shard-dg2-set2:     [INCOMPLETE][46] ([Intel XE#2705] / [Intel XE#4212] / [Intel XE#4345]) -> [PASS][47]
   [46]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-dg2-436/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc.html
   [47]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc.html

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc@pipe-b-dp-4:
    - shard-dg2-set2:     [INCOMPLETE][48] ([Intel XE#2705] / [Intel XE#4212]) -> [PASS][49]
   [48]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-dg2-436/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc@pipe-b-dp-4.html
   [49]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-463/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc@pipe-b-dp-4.html

  * igt@kms_cursor_edge_walk@256x256-top-bottom:
    - shard-adlp:         [DMESG-WARN][50] ([Intel XE#2953] / [Intel XE#4173]) -> [PASS][51] +6 other tests pass
   [50]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-adlp-3/igt@kms_cursor_edge_walk@256x256-top-bottom.html
   [51]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-9/igt@kms_cursor_edge_walk@256x256-top-bottom.html

  * igt@xe_oa@non-zero-reason-all:
    - shard-lnl:          [FAIL][52] ([Intel XE#6332]) -> [PASS][53] +1 other test pass
   [52]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-lnl-3/igt@xe_oa@non-zero-reason-all.html
   [53]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-lnl-4/igt@xe_oa@non-zero-reason-all.html

  
#### Warnings ####

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs:
    - shard-dg2-set2:     [INCOMPLETE][54] ([Intel XE#2705] / [Intel XE#4212] / [Intel XE#4345]) -> [INCOMPLETE][55] ([Intel XE#1727] / [Intel XE#3113] / [Intel XE#4345] / [Intel XE#6168])
   [54]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-dg2-464/igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs.html
   [55]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-435/igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs.html

  * igt@xe_exec_basic@multigpu-once-null-defer-bind:
    - shard-dg2-set2:     [INCOMPLETE][56] -> [INCOMPLETE][57] ([Intel XE#4842])
   [56]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-dg2-463/igt@xe_exec_basic@multigpu-once-null-defer-bind.html
   [57]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-dg2-436/igt@xe_exec_basic@multigpu-once-null-defer-bind.html

  * igt@xe_sriov_scheduling@equal-throughput:
    - shard-adlp:         [DMESG-FAIL][58] ([Intel XE#3868] / [Intel XE#5213]) -> [DMESG-FAIL][59] ([Intel XE#3868] / [Intel XE#5213] / [Intel XE#5545]) +1 other test dmesg-fail
   [58]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7/shard-adlp-6/igt@xe_sriov_scheduling@equal-throughput.html
   [59]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/shard-adlp-3/igt@xe_sriov_scheduling@equal-throughput.html

  
  [Intel XE#1124]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1124
  [Intel XE#1392]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1392
  [Intel XE#1406]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1406
  [Intel XE#1489]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1489
  [Intel XE#1727]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1727
  [Intel XE#2191]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2191
  [Intel XE#2284]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2284
  [Intel XE#2705]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2705
  [Intel XE#2850]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2850
  [Intel XE#288]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/288
  [Intel XE#2907]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2907
  [Intel XE#2953]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2953
  [Intel XE#309]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/309
  [Intel XE#3113]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3113
  [Intel XE#316]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/316
  [Intel XE#3573]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3573
  [Intel XE#366]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/366
  [Intel XE#367]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/367
  [Intel XE#373]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/373
  [Intel XE#3868]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3868
  [Intel XE#4173]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4173
  [Intel XE#4212]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4212
  [Intel XE#4345]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4345
  [Intel XE#455]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/455
  [Intel XE#4733]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4733
  [Intel XE#4837]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4837
  [Intel XE#4842]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4842
  [Intel XE#4915]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4915
  [Intel XE#5213]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5213
  [Intel XE#5545]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5545
  [Intel XE#5561]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5561
  [Intel XE#5575]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5575
  [Intel XE#6054]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6054
  [Intel XE#6168]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6168
  [Intel XE#6251]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6251
  [Intel XE#6332]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6332
  [Intel XE#651]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/651
  [Intel XE#653]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/653
  [Intel XE#656]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/656
  [Intel XE#787]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/787
  [Intel XE#836]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/836
  [Intel XE#929]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/929
  [Intel XE#944]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/944


Build changes
-------------

  * Linux: xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7 -> xe-pw-156865v3

  IGT_8636: 254cd102396ff95d61f2ebe49fc09128878bf483 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  xe-4135-3d718db04a365cc44a3bc81ffa4db7bbd2e645d7: 3d718db04a365cc44a3bc81ffa4db7bbd2e645d7
  xe-pw-156865v3: 156865v3

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-156865v3/index.html

[-- Attachment #2: Type: text/html, Size: 22927 bytes --]

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

* Re: [PATCH v3 10/18] drm/xe/multi_queue: Set QUEUE_DRAIN_MODE for Multi Queue batches
  2025-11-21  3:51 ` [PATCH v3 10/18] drm/xe/multi_queue: Set QUEUE_DRAIN_MODE for Multi Queue batches Niranjana Vishwanathapura
@ 2025-11-24 18:49   ` Matt Roper
  2025-12-02 21:28     ` Niranjana Vishwanathapura
  0 siblings, 1 reply; 41+ messages in thread
From: Matt Roper @ 2025-11-24 18:49 UTC (permalink / raw)
  To: Niranjana Vishwanathapura; +Cc: intel-xe, matthew.brost

On Thu, Nov 20, 2025 at 07:51:44PM -0800, Niranjana Vishwanathapura wrote:
> To properly support soft light restore between batches
> being arbitrated at the CFEG, PIPE_CONTROL instructions
> have a new bit in the first DW, QUEUE_DRAIN_MODE. When
> set, this indicates to the CFEG that it should only
> drain the current queue.
> 
> Additionally we no longer want to set the CS_STALL bit
> for these multi queue queues as this causes the entire
> pipeline to stall waiting for completion of the prior
> batch, preventing this soft light restore from occurring
> between queues in a queue group.
> 
> Bspec: 56551
> Signed-off-by: Stuart Summers <stuart.summers@intel.com>
> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
> ---
>  .../gpu/drm/xe/instructions/xe_gpu_commands.h |  1 +
>  drivers/gpu/drm/xe/xe_ring_ops.c              | 68 ++++++++++++-------
>  2 files changed, 45 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h b/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h
> index 5d41ca297447..885fcf211e6d 100644
> --- a/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h
> +++ b/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h
> @@ -47,6 +47,7 @@
>  
>  #define GFX_OP_PIPE_CONTROL(len)	((0x3<<29)|(0x3<<27)|(0x2<<24)|((len)-2))
>  
> +#define   PIPE_CONTROL0_QUEUE_DRAIN_MODE		BIT(12)
>  #define	  PIPE_CONTROL0_L3_READ_ONLY_CACHE_INVALIDATE	BIT(10)	/* gen12 */
>  #define	  PIPE_CONTROL0_HDC_PIPELINE_FLUSH		BIT(9)	/* gen12 */
>  
> diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c
> index ac0c6dcffe15..71f0e19fe8ba 100644
> --- a/drivers/gpu/drm/xe/xe_ring_ops.c
> +++ b/drivers/gpu/drm/xe/xe_ring_ops.c
> @@ -12,7 +12,7 @@
>  #include "regs/xe_engine_regs.h"
>  #include "regs/xe_gt_regs.h"
>  #include "regs/xe_lrc_layout.h"
> -#include "xe_exec_queue_types.h"
> +#include "xe_exec_queue.h"
>  #include "xe_gt.h"
>  #include "xe_lrc.h"
>  #include "xe_macros.h"
> @@ -135,12 +135,11 @@ emit_pipe_control(u32 *dw, int i, u32 bit_group_0, u32 bit_group_1, u32 offset,
>  	return i;
>  }
>  
> -static int emit_pipe_invalidate(u32 mask_flags, bool invalidate_tlb, u32 *dw,
> -				int i)
> +static int emit_pipe_invalidate(struct xe_exec_queue *q, u32 mask_flags,
> +				bool invalidate_tlb, u32 *dw, int i)
>  {
>  	u32 flags0 = 0;
> -	u32 flags1 = PIPE_CONTROL_CS_STALL |
> -		PIPE_CONTROL_COMMAND_CACHE_INVALIDATE |
> +	u32 flags1 = PIPE_CONTROL_COMMAND_CACHE_INVALIDATE |
>  		PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE |
>  		PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
>  		PIPE_CONTROL_VF_CACHE_INVALIDATE |
> @@ -152,6 +151,11 @@ static int emit_pipe_invalidate(u32 mask_flags, bool invalidate_tlb, u32 *dw,
>  	if (invalidate_tlb)
>  		flags1 |= PIPE_CONTROL_TLB_INVALIDATE;
>  
> +	if (xe_exec_queue_is_multi_queue(q))
> +		flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
> +	else
> +		flags1 |= PIPE_CONTROL_CS_STALL;
> +
>  	flags1 &= ~mask_flags;
>  
>  	if (flags1 & PIPE_CONTROL_VF_CACHE_INVALIDATE)
> @@ -175,54 +179,70 @@ static int emit_store_imm_ppgtt_posted(u64 addr, u64 value,
>  
>  static int emit_render_cache_flush(struct xe_sched_job *job, u32 *dw, int i)
>  {
> -	struct xe_gt *gt = job->q->gt;
> +	struct xe_exec_queue *q = job->q;
> +	struct xe_gt *gt = q->gt;
>  	bool lacks_render = !(gt->info.engine_mask & XE_HW_ENGINE_RCS_MASK);
> -	u32 flags;
> +	u32 flags0, flags1;
>  
>  	if (XE_GT_WA(gt, 14016712196))
>  		i = emit_pipe_control(dw, i, 0, PIPE_CONTROL_DEPTH_CACHE_FLUSH,
>  				      LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR, 0);
>  
> -	flags = (PIPE_CONTROL_CS_STALL |
> -		 PIPE_CONTROL_TILE_CACHE_FLUSH |
> +	flags0 = PIPE_CONTROL0_HDC_PIPELINE_FLUSH;
> +	flags1 = (PIPE_CONTROL_TILE_CACHE_FLUSH |
>  		 PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
>  		 PIPE_CONTROL_DEPTH_CACHE_FLUSH |
>  		 PIPE_CONTROL_DC_FLUSH_ENABLE |
>  		 PIPE_CONTROL_FLUSH_ENABLE);
>  
>  	if (XE_GT_WA(gt, 1409600907))
> -		flags |= PIPE_CONTROL_DEPTH_STALL;
> +		flags1 |= PIPE_CONTROL_DEPTH_STALL;
>  
>  	if (lacks_render)
> -		flags &= ~PIPE_CONTROL_3D_ARCH_FLAGS;
> +		flags1 &= ~PIPE_CONTROL_3D_ARCH_FLAGS;
>  	else if (job->q->class == XE_ENGINE_CLASS_COMPUTE)
> -		flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
> +		flags1 &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
> +
> +	if (xe_exec_queue_is_multi_queue(q))
> +		flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
> +	else
> +		flags1 |= PIPE_CONTROL_CS_STALL;
>  
> -	return emit_pipe_control(dw, i, PIPE_CONTROL0_HDC_PIPELINE_FLUSH, flags, 0, 0);
> +	return emit_pipe_control(dw, i, flags0, flags1, 0, 0);
>  }
>  
> -static int emit_pipe_control_to_ring_end(struct xe_hw_engine *hwe, u32 *dw, int i)
> +static int emit_pipe_control_to_ring_end(struct xe_exec_queue *q, u32 *dw, int i)
>  {
> +	u32 flags0 = 0, flags1 = PIPE_CONTROL_LRI_POST_SYNC;
> +	struct xe_hw_engine *hwe = q->hwe;
> +
>  	if (hwe->class != XE_ENGINE_CLASS_RENDER)
>  		return i;
>  
> +	if (xe_exec_queue_is_multi_queue(q))

We probably don't need to worry about converting in this function since
it's only used by an Xe2 workaround and will be removed completely once
https://patchwork.freedesktop.org/patch/689424/?series=157804&rev=2
lands.  If you want to be safe, you could just make it an assertion for
!multi_queue since that should never be possible on Xe2.

Anyway, the changes look good overall so

Reviewed-by: Matt Roper <matthew.d.roper@intel.com>

> +		flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
> +
>  	if (XE_GT_WA(hwe->gt, 16020292621))
> -		i = emit_pipe_control(dw, i, 0, PIPE_CONTROL_LRI_POST_SYNC,
> +		i = emit_pipe_control(dw, i, flags0, flags1,
>  				      RING_NOPID(hwe->mmio_base).addr, 0);
>  
>  	return i;
>  }
>  
> -static int emit_pipe_imm_ggtt(u32 addr, u32 value, bool stall_only, u32 *dw,
> -			      int i)
> +static int emit_pipe_imm_ggtt(struct xe_exec_queue *q, u32 addr, u32 value,
> +			      bool stall_only, u32 *dw, int i)
>  {
> -	u32 flags = PIPE_CONTROL_CS_STALL | PIPE_CONTROL_GLOBAL_GTT_IVB |
> -		    PIPE_CONTROL_QW_WRITE;
> +	u32 flags0 = 0, flags1 = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_QW_WRITE;
>  
>  	if (!stall_only)
> -		flags |= PIPE_CONTROL_FLUSH_ENABLE;
> +		flags1 |= PIPE_CONTROL_FLUSH_ENABLE;
> +
> +	if (xe_exec_queue_is_multi_queue(q))
> +		flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
> +	else
> +		flags1 |= PIPE_CONTROL_CS_STALL;
>  
> -	return emit_pipe_control(dw, i, 0, flags, addr, value);
> +	return emit_pipe_control(dw, i, flags0, flags1, addr, value);
>  }
>  
>  static u32 get_ppgtt_flag(struct xe_sched_job *job)
> @@ -371,7 +391,7 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job,
>  		mask_flags = PIPE_CONTROL_3D_ENGINE_FLAGS;
>  
>  	/* See __xe_pt_bind_vma() for a discussion on TLB invalidations. */
> -	i = emit_pipe_invalidate(mask_flags, job->ring_ops_flush_tlb, dw, i);
> +	i = emit_pipe_invalidate(job->q, mask_flags, job->ring_ops_flush_tlb, dw, i);
>  
>  	/* hsdes: 1809175790 */
>  	if (has_aux_ccs(xe))
> @@ -391,11 +411,11 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job,
>  						job->user_fence.value,
>  						dw, i);
>  
> -	i = emit_pipe_imm_ggtt(xe_lrc_seqno_ggtt_addr(lrc), seqno, lacks_render, dw, i);
> +	i = emit_pipe_imm_ggtt(job->q, xe_lrc_seqno_ggtt_addr(lrc), seqno, lacks_render, dw, i);
>  
>  	i = emit_user_interrupt(dw, i);
>  
> -	i = emit_pipe_control_to_ring_end(job->q->hwe, dw, i);
> +	i = emit_pipe_control_to_ring_end(job->q, dw, i);
>  
>  	xe_gt_assert(gt, i <= MAX_JOB_SIZE_DW);
>  
> -- 
> 2.43.0
> 

-- 
Matt Roper
Graphics Software Engineer
Linux GPU Platform Enablement
Intel Corporation

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

* RE: [PATCH v3 00/18] drm/xe: Multi Queue feature support
  2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
                   ` (22 preceding siblings ...)
  2025-11-24 14:04 ` Patchwork
@ 2025-11-27  9:38 ` Hoppe, Mateusz
  23 siblings, 0 replies; 41+ messages in thread
From: Hoppe, Mateusz @ 2025-11-27  9:38 UTC (permalink / raw)
  To: Vishwanathapura, Niranjana, intel-xe@lists.freedesktop.org; +Cc: Brost, Matthew

The multi-queue uapi in this series looks good for the compute use case.
Acked-by: Mateusz Hoppe <mateusz.hoppe@intel.com>


-----Original Message-----
From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Niranjana Vishwanathapura
Sent: Friday, November 21, 2025 4:52 AM
To: intel-xe@lists.freedesktop.org
Cc: matthew.brost@intel.com
Subject: [PATCH v3 00/18] drm/xe: Multi Queue feature support

Multi Queue is a new mode of execution supported by the compute and blitter copy command streamers (CCS and BCS, respectively). It is an enhancement of the existing hardware architecture and leverages the same submission model. It enables support for efficient, parallel execution of multiple queues within a single context.

Add support for multi-queue feature and enable it on xe3p_xpc.

The associated IGT patch series is,
https://patchwork.freedesktop.org/series/156866/

The Compute UMD usecase is,
https://github.com/intel/compute-runtime/pull/862

Changes in v2:
- Rename multi_queue_enable_mask to multi_queue_engine_class_mask.
- Remove group->lock, fix function semantics, add additional comments,
  add asserts, update uapi kernel-doc, move group->list_lock to right
  patch, add XE_BO_FLAG_GGTT_INVALIDATE for cgp bo.
- Fix G2H_LEN_DW_MULTI_QUEUE_CONTEXT value.
- Add fs_reclaim lock dependency, add bspec ref, other minor cleanups.

Changes in v3:
- Add patch "drm/xe/xe3p: Disable GuC Dynamic ICS for Xe3p"
- Add patch "drm/xe/multi_queue: Reset GT upon CGP_SYNC failure"
- Code refactoring and kernel-doc update
- Assert CGP_SYNC message length is valid
- For CGP bo use PINNED_LATE_RESTORE/USER_VRAM/GGTT_INVALIDATE flags
- Properly handle cleanup of multi-queue group

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>

Gustavo Sousa (1):
  drm/xe/xe3p: Disable GuC Dynamic ICS for Xe3p

Niranjana Vishwanathapura (17):
  drm/xe/multi_queue: Add multi_queue_enable_mask to gt information
  drm/xe/multi_queue: Add user interface for multi queue support
  drm/xe/multi_queue: Add GuC interface for multi queue support
  drm/xe/multi_queue: Add multi queue priority property
  drm/xe/multi_queue: Handle invalid exec queue property setting
  drm/xe/multi_queue: Add exec_queue set_property ioctl support
  drm/xe/multi_queue: Add support for multi queue dynamic priority
    change
  drm/xe/multi_queue: Add multi queue information to guc_info dump
  drm/xe/multi_queue: Handle tearing down of a multi queue
  drm/xe/multi_queue: Set QUEUE_DRAIN_MODE for Multi Queue batches
  drm/xe/multi_queue: Handle CGP context error
  drm/xe/multi_queue: Reset GT upon CGP_SYNC failure
  drm/xe/multi_queue: Tracepoint support
  drm/xe/multi_queue: Support active group after primary is destroyed
  drm/xe/doc: Add documentation for Multi Queue Group
  drm/xe/doc: Add documentation for Multi Queue Group GuC interface
  drm/xe/multi_queue: Enable multi_queue on xe3p_xpc

 Documentation/gpu/xe/xe_exec_queue.rst        |  14 +
 drivers/gpu/drm/xe/abi/guc_actions_abi.h      |   4 +
 .../gpu/drm/xe/instructions/xe_gpu_commands.h |   1 +
 drivers/gpu/drm/xe/xe_debugfs.c               |   2 +
 drivers/gpu/drm/xe/xe_device.c                |   9 +-
 drivers/gpu/drm/xe/xe_exec_queue.c            | 428 +++++++++++-
 drivers/gpu/drm/xe/xe_exec_queue.h            |  51 ++
 drivers/gpu/drm/xe/xe_exec_queue_types.h      |  57 ++
 drivers/gpu/drm/xe/xe_gt_types.h              |   5 +
 drivers/gpu/drm/xe/xe_guc.c                   |   7 +
 drivers/gpu/drm/xe/xe_guc_ct.c                |   8 +
 drivers/gpu/drm/xe/xe_guc_fwif.h              |   3 +
 drivers/gpu/drm/xe/xe_guc_submit.c            | 627 ++++++++++++++++--
 drivers/gpu/drm/xe/xe_guc_submit.h            |   3 +
 drivers/gpu/drm/xe/xe_guc_submit_types.h      |  13 +
 drivers/gpu/drm/xe/xe_lrc.c                   |  29 +
 drivers/gpu/drm/xe/xe_lrc.h                   |   3 +
 drivers/gpu/drm/xe/xe_pci.c                   |   3 +
 drivers/gpu/drm/xe/xe_pci_types.h             |   1 +
 drivers/gpu/drm/xe/xe_ring_ops.c              |  68 +-
 drivers/gpu/drm/xe/xe_trace.h                 |  46 ++
 include/uapi/drm/xe_drm.h                     |  44 ++
 22 files changed, 1335 insertions(+), 91 deletions(-)

--
2.43.0


---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Spolka oswiadcza, ze posiada status duzego przedsiebiorcy w rozumieniu ustawy z dnia 8 marca 2013 r. o przeciwdzialaniu nadmiernym opoznieniom w transakcjach handlowych.

Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.


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

* Re: [PATCH v3 10/18] drm/xe/multi_queue: Set QUEUE_DRAIN_MODE for Multi Queue batches
  2025-11-24 18:49   ` Matt Roper
@ 2025-12-02 21:28     ` Niranjana Vishwanathapura
  0 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-12-02 21:28 UTC (permalink / raw)
  To: Matt Roper; +Cc: intel-xe, matthew.brost

On Mon, Nov 24, 2025 at 10:49:35AM -0800, Matt Roper wrote:
>On Thu, Nov 20, 2025 at 07:51:44PM -0800, Niranjana Vishwanathapura wrote:
>> To properly support soft light restore between batches
>> being arbitrated at the CFEG, PIPE_CONTROL instructions
>> have a new bit in the first DW, QUEUE_DRAIN_MODE. When
>> set, this indicates to the CFEG that it should only
>> drain the current queue.
>>
>> Additionally we no longer want to set the CS_STALL bit
>> for these multi queue queues as this causes the entire
>> pipeline to stall waiting for completion of the prior
>> batch, preventing this soft light restore from occurring
>> between queues in a queue group.
>>
>> Bspec: 56551
>> Signed-off-by: Stuart Summers <stuart.summers@intel.com>
>> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
>> ---
>>  .../gpu/drm/xe/instructions/xe_gpu_commands.h |  1 +
>>  drivers/gpu/drm/xe/xe_ring_ops.c              | 68 ++++++++++++-------
>>  2 files changed, 45 insertions(+), 24 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h b/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h
>> index 5d41ca297447..885fcf211e6d 100644
>> --- a/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h
>> +++ b/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h
>> @@ -47,6 +47,7 @@
>>
>>  #define GFX_OP_PIPE_CONTROL(len)	((0x3<<29)|(0x3<<27)|(0x2<<24)|((len)-2))
>>
>> +#define   PIPE_CONTROL0_QUEUE_DRAIN_MODE		BIT(12)
>>  #define	  PIPE_CONTROL0_L3_READ_ONLY_CACHE_INVALIDATE	BIT(10)	/* gen12 */
>>  #define	  PIPE_CONTROL0_HDC_PIPELINE_FLUSH		BIT(9)	/* gen12 */
>>
>> diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c
>> index ac0c6dcffe15..71f0e19fe8ba 100644
>> --- a/drivers/gpu/drm/xe/xe_ring_ops.c
>> +++ b/drivers/gpu/drm/xe/xe_ring_ops.c
>> @@ -12,7 +12,7 @@
>>  #include "regs/xe_engine_regs.h"
>>  #include "regs/xe_gt_regs.h"
>>  #include "regs/xe_lrc_layout.h"
>> -#include "xe_exec_queue_types.h"
>> +#include "xe_exec_queue.h"
>>  #include "xe_gt.h"
>>  #include "xe_lrc.h"
>>  #include "xe_macros.h"
>> @@ -135,12 +135,11 @@ emit_pipe_control(u32 *dw, int i, u32 bit_group_0, u32 bit_group_1, u32 offset,
>>  	return i;
>>  }
>>
>> -static int emit_pipe_invalidate(u32 mask_flags, bool invalidate_tlb, u32 *dw,
>> -				int i)
>> +static int emit_pipe_invalidate(struct xe_exec_queue *q, u32 mask_flags,
>> +				bool invalidate_tlb, u32 *dw, int i)
>>  {
>>  	u32 flags0 = 0;
>> -	u32 flags1 = PIPE_CONTROL_CS_STALL |
>> -		PIPE_CONTROL_COMMAND_CACHE_INVALIDATE |
>> +	u32 flags1 = PIPE_CONTROL_COMMAND_CACHE_INVALIDATE |
>>  		PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE |
>>  		PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
>>  		PIPE_CONTROL_VF_CACHE_INVALIDATE |
>> @@ -152,6 +151,11 @@ static int emit_pipe_invalidate(u32 mask_flags, bool invalidate_tlb, u32 *dw,
>>  	if (invalidate_tlb)
>>  		flags1 |= PIPE_CONTROL_TLB_INVALIDATE;
>>
>> +	if (xe_exec_queue_is_multi_queue(q))
>> +		flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
>> +	else
>> +		flags1 |= PIPE_CONTROL_CS_STALL;
>> +
>>  	flags1 &= ~mask_flags;
>>
>>  	if (flags1 & PIPE_CONTROL_VF_CACHE_INVALIDATE)
>> @@ -175,54 +179,70 @@ static int emit_store_imm_ppgtt_posted(u64 addr, u64 value,
>>
>>  static int emit_render_cache_flush(struct xe_sched_job *job, u32 *dw, int i)
>>  {
>> -	struct xe_gt *gt = job->q->gt;
>> +	struct xe_exec_queue *q = job->q;
>> +	struct xe_gt *gt = q->gt;
>>  	bool lacks_render = !(gt->info.engine_mask & XE_HW_ENGINE_RCS_MASK);
>> -	u32 flags;
>> +	u32 flags0, flags1;
>>
>>  	if (XE_GT_WA(gt, 14016712196))
>>  		i = emit_pipe_control(dw, i, 0, PIPE_CONTROL_DEPTH_CACHE_FLUSH,
>>  				      LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR, 0);
>>
>> -	flags = (PIPE_CONTROL_CS_STALL |
>> -		 PIPE_CONTROL_TILE_CACHE_FLUSH |
>> +	flags0 = PIPE_CONTROL0_HDC_PIPELINE_FLUSH;
>> +	flags1 = (PIPE_CONTROL_TILE_CACHE_FLUSH |
>>  		 PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
>>  		 PIPE_CONTROL_DEPTH_CACHE_FLUSH |
>>  		 PIPE_CONTROL_DC_FLUSH_ENABLE |
>>  		 PIPE_CONTROL_FLUSH_ENABLE);
>>
>>  	if (XE_GT_WA(gt, 1409600907))
>> -		flags |= PIPE_CONTROL_DEPTH_STALL;
>> +		flags1 |= PIPE_CONTROL_DEPTH_STALL;
>>
>>  	if (lacks_render)
>> -		flags &= ~PIPE_CONTROL_3D_ARCH_FLAGS;
>> +		flags1 &= ~PIPE_CONTROL_3D_ARCH_FLAGS;
>>  	else if (job->q->class == XE_ENGINE_CLASS_COMPUTE)
>> -		flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
>> +		flags1 &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
>> +
>> +	if (xe_exec_queue_is_multi_queue(q))
>> +		flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
>> +	else
>> +		flags1 |= PIPE_CONTROL_CS_STALL;
>>
>> -	return emit_pipe_control(dw, i, PIPE_CONTROL0_HDC_PIPELINE_FLUSH, flags, 0, 0);
>> +	return emit_pipe_control(dw, i, flags0, flags1, 0, 0);
>>  }
>>
>> -static int emit_pipe_control_to_ring_end(struct xe_hw_engine *hwe, u32 *dw, int i)
>> +static int emit_pipe_control_to_ring_end(struct xe_exec_queue *q, u32 *dw, int i)
>>  {
>> +	u32 flags0 = 0, flags1 = PIPE_CONTROL_LRI_POST_SYNC;
>> +	struct xe_hw_engine *hwe = q->hwe;
>> +
>>  	if (hwe->class != XE_ENGINE_CLASS_RENDER)
>>  		return i;
>>
>> +	if (xe_exec_queue_is_multi_queue(q))
>
>We probably don't need to worry about converting in this function since
>it's only used by an Xe2 workaround and will be removed completely once
>https://patchwork.freedesktop.org/patch/689424/?series=157804&rev=2
>lands.  If you want to be safe, you could just make it an assertion for
>!multi_queue since that should never be possible on Xe2.
>

Ok, will remove the change here and instead add an !multi_queue assert.

Thanks,
Niranjana

>Anyway, the changes look good overall so
>
>Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
>
>> +		flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
>> +
>>  	if (XE_GT_WA(hwe->gt, 16020292621))
>> -		i = emit_pipe_control(dw, i, 0, PIPE_CONTROL_LRI_POST_SYNC,
>> +		i = emit_pipe_control(dw, i, flags0, flags1,
>>  				      RING_NOPID(hwe->mmio_base).addr, 0);
>>
>>  	return i;
>>  }
>>
>> -static int emit_pipe_imm_ggtt(u32 addr, u32 value, bool stall_only, u32 *dw,
>> -			      int i)
>> +static int emit_pipe_imm_ggtt(struct xe_exec_queue *q, u32 addr, u32 value,
>> +			      bool stall_only, u32 *dw, int i)
>>  {
>> -	u32 flags = PIPE_CONTROL_CS_STALL | PIPE_CONTROL_GLOBAL_GTT_IVB |
>> -		    PIPE_CONTROL_QW_WRITE;
>> +	u32 flags0 = 0, flags1 = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_QW_WRITE;
>>
>>  	if (!stall_only)
>> -		flags |= PIPE_CONTROL_FLUSH_ENABLE;
>> +		flags1 |= PIPE_CONTROL_FLUSH_ENABLE;
>> +
>> +	if (xe_exec_queue_is_multi_queue(q))
>> +		flags0 |= PIPE_CONTROL0_QUEUE_DRAIN_MODE;
>> +	else
>> +		flags1 |= PIPE_CONTROL_CS_STALL;
>>
>> -	return emit_pipe_control(dw, i, 0, flags, addr, value);
>> +	return emit_pipe_control(dw, i, flags0, flags1, addr, value);
>>  }
>>
>>  static u32 get_ppgtt_flag(struct xe_sched_job *job)
>> @@ -371,7 +391,7 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job,
>>  		mask_flags = PIPE_CONTROL_3D_ENGINE_FLAGS;
>>
>>  	/* See __xe_pt_bind_vma() for a discussion on TLB invalidations. */
>> -	i = emit_pipe_invalidate(mask_flags, job->ring_ops_flush_tlb, dw, i);
>> +	i = emit_pipe_invalidate(job->q, mask_flags, job->ring_ops_flush_tlb, dw, i);
>>
>>  	/* hsdes: 1809175790 */
>>  	if (has_aux_ccs(xe))
>> @@ -391,11 +411,11 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job,
>>  						job->user_fence.value,
>>  						dw, i);
>>
>> -	i = emit_pipe_imm_ggtt(xe_lrc_seqno_ggtt_addr(lrc), seqno, lacks_render, dw, i);
>> +	i = emit_pipe_imm_ggtt(job->q, xe_lrc_seqno_ggtt_addr(lrc), seqno, lacks_render, dw, i);
>>
>>  	i = emit_user_interrupt(dw, i);
>>
>> -	i = emit_pipe_control_to_ring_end(job->q->hwe, dw, i);
>> +	i = emit_pipe_control_to_ring_end(job->q, dw, i);
>>
>>  	xe_gt_assert(gt, i <= MAX_JOB_SIZE_DW);
>>
>> --
>> 2.43.0
>>
>
>-- 
>Matt Roper
>Graphics Software Engineer
>Linux GPU Platform Enablement
>Intel Corporation

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

* Re: [PATCH v3 03/18] drm/xe/multi_queue: Add GuC interface for multi queue support
  2025-11-22 22:16   ` Matthew Brost
@ 2025-12-03  3:40     ` Niranjana Vishwanathapura
  0 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-12-03  3:40 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe

On Sat, Nov 22, 2025 at 02:16:00PM -0800, Matthew Brost wrote:
>On Thu, Nov 20, 2025 at 07:51:37PM -0800, Niranjana Vishwanathapura wrote:
>> Implement GuC commands and response along with the Context
>> Group Page (CGP) interface for multi queue support.
>>
>> Ensure that only primary queue (q0) of a multi queue group
>> communicate with GuC. The secondary queues of the group only
>> need to maintain LRCA and interface with drm scheduler.
>>
>> Use primary queue's submit_wq for all secondary queues of a multi
>> queue group. This serialization avoids any locking around CGP
>> synchronization with GuC.
>>
>> v2: Fix G2H_LEN_DW_MULTI_QUEUE_CONTEXT value, add more comments
>>     (Matt Brost)
>> v3: Minor code refactro, use xe_gt_assert
>>
>> Signed-off-by: Stuart Summers <stuart.summers@intel.com>
>> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
>> ---
>>  drivers/gpu/drm/xe/abi/guc_actions_abi.h |   3 +
>>  drivers/gpu/drm/xe/xe_exec_queue_types.h |   2 +
>>  drivers/gpu/drm/xe/xe_guc_ct.c           |   4 +
>>  drivers/gpu/drm/xe/xe_guc_fwif.h         |   3 +
>>  drivers/gpu/drm/xe/xe_guc_submit.c       | 276 +++++++++++++++++++++--
>>  drivers/gpu/drm/xe/xe_guc_submit.h       |   1 +
>>  6 files changed, 267 insertions(+), 22 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/xe/abi/guc_actions_abi.h b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
>> index 47756e4674a1..3e9fbed9cda6 100644
>> --- a/drivers/gpu/drm/xe/abi/guc_actions_abi.h
>> +++ b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
>> @@ -139,6 +139,9 @@ enum xe_guc_action {
>>  	XE_GUC_ACTION_DEREGISTER_G2G = 0x4508,
>>  	XE_GUC_ACTION_DEREGISTER_CONTEXT_DONE = 0x4600,
>>  	XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC = 0x4601,
>> +	XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE = 0x4602,
>> +	XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC = 0x4603,
>> +	XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE = 0x4604,
>>  	XE_GUC_ACTION_CLIENT_SOFT_RESET = 0x5507,
>>  	XE_GUC_ACTION_SET_ENG_UTIL_BUFF = 0x550A,
>>  	XE_GUC_ACTION_SET_DEVICE_ENGINE_ACTIVITY_BUFFER = 0x550C,
>> diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> index f429b1952be9..b9da51ab7eaf 100644
>> --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> @@ -44,6 +44,8 @@ struct xe_exec_queue_group {
>>  	struct xe_bo *cgp_bo;
>>  	/** @xa: xarray to store LRCs */
>>  	struct xarray xa;
>> +	/** @sync_pending: CGP_SYNC_DONE g2h response pending */
>> +	bool sync_pending;
>>  };
>>
>>  /**
>> diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c
>> index 2697d711adb2..43a79bcdfb18 100644
>> --- a/drivers/gpu/drm/xe/xe_guc_ct.c
>> +++ b/drivers/gpu/drm/xe/xe_guc_ct.c
>> @@ -1307,6 +1307,7 @@ static int parse_g2h_event(struct xe_guc_ct *ct, u32 *msg, u32 len)
>>  	lockdep_assert_held(&ct->lock);
>>
>>  	switch (action) {
>> +	case XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE:
>>  	case XE_GUC_ACTION_SCHED_CONTEXT_MODE_DONE:
>>  	case XE_GUC_ACTION_DEREGISTER_CONTEXT_DONE:
>>  	case XE_GUC_ACTION_SCHED_ENGINE_MODE_DONE:
>> @@ -1569,6 +1570,9 @@ static int process_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len)
>>  		ret = xe_guc_g2g_test_notification(guc, payload, adj_len);
>>  		break;
>>  #endif
>> +	case XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE:
>> +		ret = xe_guc_exec_queue_cgp_sync_done_handler(guc, payload, adj_len);
>> +		break;
>>  	default:
>>  		xe_gt_err(gt, "unexpected G2H action 0x%04x\n", action);
>>  	}
>> diff --git a/drivers/gpu/drm/xe/xe_guc_fwif.h b/drivers/gpu/drm/xe/xe_guc_fwif.h
>> index c90dd266e9cf..9b090d9b95f1 100644
>> --- a/drivers/gpu/drm/xe/xe_guc_fwif.h
>> +++ b/drivers/gpu/drm/xe/xe_guc_fwif.h
>> @@ -16,6 +16,7 @@
>>  #define G2H_LEN_DW_DEREGISTER_CONTEXT		3
>>  #define G2H_LEN_DW_TLB_INVALIDATE		3
>>  #define G2H_LEN_DW_G2G_NOTIFY_MIN		3
>> +#define G2H_LEN_DW_MULTI_QUEUE_CONTEXT		3
>>
>>  #define GUC_ID_MAX			65535
>>  #define GUC_ID_UNKNOWN			0xffffffff
>> @@ -62,6 +63,8 @@ struct guc_ctxt_registration_info {
>>  	u32 wq_base_lo;
>>  	u32 wq_base_hi;
>>  	u32 wq_size;
>> +	u32 cgp_lo;
>> +	u32 cgp_hi;
>>  	u32 hwlrca_lo;
>>  	u32 hwlrca_hi;
>>  };
>> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
>> index 7e0882074a99..c68739fd7592 100644
>> --- a/drivers/gpu/drm/xe/xe_guc_submit.c
>> +++ b/drivers/gpu/drm/xe/xe_guc_submit.c
>> @@ -19,6 +19,7 @@
>>  #include "abi/guc_klvs_abi.h"
>>  #include "regs/xe_lrc_layout.h"
>>  #include "xe_assert.h"
>> +#include "xe_bo.h"
>>  #include "xe_devcoredump.h"
>>  #include "xe_device.h"
>>  #include "xe_exec_queue.h"
>> @@ -541,7 +542,8 @@ static void init_policies(struct xe_guc *guc, struct xe_exec_queue *q)
>>  	u32 slpc_exec_queue_freq_req = 0;
>>  	u32 preempt_timeout_us = q->sched_props.preempt_timeout_us;
>>
>> -	xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q));
>> +	xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q) &&
>> +		     !xe_exec_queue_is_multi_queue_secondary(q));
>>
>>  	if (q->flags & EXEC_QUEUE_FLAG_LOW_LATENCY)
>>  		slpc_exec_queue_freq_req |= SLPC_CTX_FREQ_REQ_IS_COMPUTE;
>> @@ -561,6 +563,8 @@ static void set_min_preemption_timeout(struct xe_guc *guc, struct xe_exec_queue
>>  {
>>  	struct exec_queue_policy policy;
>>
>> +	xe_assert(guc_to_xe(guc), !xe_exec_queue_is_multi_queue_secondary(q));
>> +
>>  	__guc_exec_queue_policy_start_klv(&policy, q->guc->id);
>>  	__guc_exec_queue_policy_add_preemption_timeout(&policy, 1);
>>
>> @@ -568,6 +572,11 @@ static void set_min_preemption_timeout(struct xe_guc *guc, struct xe_exec_queue
>>  		       __guc_exec_queue_policy_action_size(&policy), 0, 0);
>>  }
>>
>> +static bool vf_recovery(struct xe_guc *guc)
>> +{
>> +	return xe_gt_recovery_pending(guc_to_gt(guc));
>> +}
>> +
>>  #define parallel_read(xe_, map_, field_) \
>>  	xe_map_rd_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
>>  			field_)
>> @@ -575,6 +584,117 @@ static void set_min_preemption_timeout(struct xe_guc *guc, struct xe_exec_queue
>>  	xe_map_wr_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
>>  			field_, val_)
>>
>> +#define CGP_VERSION_MAJOR_SHIFT	8
>> +
>> +static void xe_guc_exec_queue_group_cgp_update(struct xe_device *xe,
>> +					       struct xe_exec_queue *q)
>> +{
>> +	struct xe_exec_queue_group *group = q->multi_queue.group;
>> +	u32 guc_id = group->primary->guc->id;
>> +
>> +	/* Currently implementing CGP version 1.0 */
>> +	xe_map_wr(xe, &group->cgp_bo->vmap, 0, u32,
>> +		  1 << CGP_VERSION_MAJOR_SHIFT);
>> +
>> +	xe_map_wr(xe, &group->cgp_bo->vmap,
>> +		  (32 + q->multi_queue.pos * 2) * sizeof(u32),
>> +		  u32, lower_32_bits(xe_lrc_descriptor(q->lrc[0])));
>> +
>> +	xe_map_wr(xe, &group->cgp_bo->vmap,
>> +		  (33 + q->multi_queue.pos * 2) * sizeof(u32),
>> +		  u32, guc_id);
>> +
>> +	if (q->multi_queue.pos / 32) {
>> +		xe_map_wr(xe, &group->cgp_bo->vmap, 17 * sizeof(u32),
>> +			  u32, BIT(q->multi_queue.pos % 32));
>> +		xe_map_wr(xe, &group->cgp_bo->vmap, 16 * sizeof(u32), u32, 0);
>> +	} else {
>> +		xe_map_wr(xe, &group->cgp_bo->vmap, 16 * sizeof(u32),
>> +			  u32, BIT(q->multi_queue.pos));
>> +		xe_map_wr(xe, &group->cgp_bo->vmap, 17 * sizeof(u32), u32, 0);
>> +	}
>> +}
>> +
>> +static void xe_guc_exec_queue_group_cgp_sync(struct xe_guc *guc,
>> +					     struct xe_exec_queue *q,
>> +					     const u32 *action, u32 len)
>> +{
>> +	struct xe_exec_queue_group *group = q->multi_queue.group;
>> +	struct xe_device *xe = guc_to_xe(guc);
>> +	long ret;
>> +
>> +	/*
>> +	 * As all queues of a multi queue group use single drm scheduler
>> +	 * submit workqueue, CGP synchronization with GuC are serialized.
>> +	 * Hence, no locking is required here.
>> +	 * Wait for any pending CGP_SYNC_DONE response before updating the
>> +	 * CGP page and sending CGP_SYNC message.
>> +	 */
>> +	ret = wait_event_timeout(guc->ct.wq,
>> +				 !READ_ONCE(group->sync_pending) ||
>> +				 xe_guc_read_stopped(guc), HZ);
>> +	if ((!ret && !vf_recovery(guc)) || xe_guc_read_stopped(guc)) {
>
>As this series isn't quite right for VF migration, I'd leave out any VF
>migration changes. However I'd add a "FIXME: VF migration" in a follow
>up + maybe open a Jira to track. I'd like to VF migration working for
>multi-queue by the time we remove force probe for a device with
>multi-queue, so have a bit of time and we discuss further on how to make
>this work but I think it shouldn't be too bad.

Ok, will do.

>
>> +		xe_gt_warn(guc_to_gt(guc), "Wait for CGP_SYNC_DONE response failed!\n");
>> +		return;
>> +	}
>> +
>> +	xe_guc_exec_queue_group_cgp_update(xe, q);
>> +
>> +	WRITE_ONCE(group->sync_pending, true);
>> +	xe_guc_ct_send(&guc->ct, action, len, G2H_LEN_DW_MULTI_QUEUE_CONTEXT, 1);
>> +}
>> +
>> +static void __register_exec_queue_group(struct xe_guc *guc,
>> +					struct xe_exec_queue *q,
>> +					struct guc_ctxt_registration_info *info)
>> +{
>> +#define MAX_MULTI_QUEUE_REG_SIZE	(8)
>> +	u32 action[MAX_MULTI_QUEUE_REG_SIZE];
>> +	int len = 0;
>> +
>> +	action[len++] = XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE;
>> +	action[len++] = info->flags;
>> +	action[len++] = info->context_idx;
>> +	action[len++] = info->engine_class;
>> +	action[len++] = info->engine_submit_mask;
>> +	action[len++] = 0; /* Reserved */
>> +	action[len++] = info->cgp_lo;
>> +	action[len++] = info->cgp_hi;
>> +
>> +	xe_gt_assert(guc_to_gt(guc), len <= MAX_MULTI_QUEUE_REG_SIZE);
>> +#undef MAX_MULTI_QUEUE_REG_SIZE
>> +
>> +	/*
>> +	 * The above XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_QUEUE do expect a
>> +	 * XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE response
>> +	 * from guc.
>> +	 */
>> +	xe_guc_exec_queue_group_cgp_sync(guc, q, action, len);
>> +}
>> +
>> +static void xe_guc_exec_queue_group_add(struct xe_guc *guc,
>> +					struct xe_exec_queue *q)
>> +{
>> +#define MAX_MULTI_QUEUE_CGP_SYNC_SIZE  (2)
>> +	u32 action[MAX_MULTI_QUEUE_CGP_SYNC_SIZE];
>> +	int len = 0;
>> +
>> +	xe_gt_assert(guc_to_gt(guc), xe_exec_queue_is_multi_queue_secondary(q));
>> +
>> +	action[len++] = XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC;
>> +	action[len++] = q->multi_queue.group->primary->guc->id;
>> +
>> +	xe_gt_assert(guc_to_gt(guc), len <= MAX_MULTI_QUEUE_CGP_SYNC_SIZE);
>> +#undef MAX_MULTI_QUEUE_CGP_SYNC_SIZE
>> +
>> +	/*
>> +	 * The above XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC do expect a
>> +	 * XE_GUC_ACTION_NOTIFY_MULTI_QUEUE_CONTEXT_CGP_SYNC_DONE response
>> +	 * from guc.
>> +	 */
>> +	xe_guc_exec_queue_group_cgp_sync(guc, q, action, len);
>> +}
>> +
>>  static void __register_mlrc_exec_queue(struct xe_guc *guc,
>>  				       struct xe_exec_queue *q,
>>  				       struct guc_ctxt_registration_info *info)
>> @@ -670,6 +790,13 @@ static void register_exec_queue(struct xe_exec_queue *q, int ctx_type)
>>  	info.flags = CONTEXT_REGISTRATION_FLAG_KMD |
>>  		FIELD_PREP(CONTEXT_REGISTRATION_FLAG_TYPE, ctx_type);
>>
>> +	if (xe_exec_queue_is_multi_queue(q)) {
>> +		struct xe_exec_queue_group *group = q->multi_queue.group;
>> +
>> +		info.cgp_lo = xe_bo_ggtt_addr(group->cgp_bo);
>> +		info.cgp_hi = 0;
>> +	}
>> +
>>  	if (xe_exec_queue_is_parallel(q)) {
>>  		u64 ggtt_addr = xe_lrc_parallel_ggtt_addr(lrc);
>>  		struct iosys_map map = xe_lrc_parallel_map(lrc);
>> @@ -700,11 +827,18 @@ static void register_exec_queue(struct xe_exec_queue *q, int ctx_type)
>>
>>  	set_exec_queue_registered(q);
>>  	trace_xe_exec_queue_register(q);
>> -	if (xe_exec_queue_is_parallel(q))
>> +	if (xe_exec_queue_is_multi_queue_primary(q))
>> +		__register_exec_queue_group(guc, q, &info);
>> +	else if (xe_exec_queue_is_parallel(q))
>>  		__register_mlrc_exec_queue(guc, q, &info);
>> -	else
>> +	else if (!xe_exec_queue_is_multi_queue_secondary(q))
>>  		__register_exec_queue(guc, &info);
>> -	init_policies(guc, q);
>> +
>> +	if (!xe_exec_queue_is_multi_queue_secondary(q))
>> +		init_policies(guc, q);
>> +
>> +	if (xe_exec_queue_is_multi_queue_secondary(q))
>> +		xe_guc_exec_queue_group_add(guc, q);
>>  }
>>
>>  static u32 wq_space_until_wrap(struct xe_exec_queue *q)
>> @@ -712,11 +846,6 @@ static u32 wq_space_until_wrap(struct xe_exec_queue *q)
>>  	return (WQ_SIZE - q->guc->wqi_tail);
>>  }
>>
>> -static bool vf_recovery(struct xe_guc *guc)
>> -{
>> -	return xe_gt_recovery_pending(guc_to_gt(guc));
>> -}
>> -
>>  static int wq_wait_for_space(struct xe_exec_queue *q, u32 wqi_size)
>>  {
>>  	struct xe_guc *guc = exec_queue_to_guc(q);
>> @@ -833,6 +962,12 @@ static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job)
>>  	if (exec_queue_suspended(q) && !xe_exec_queue_is_parallel(q))
>>  		return;
>>
>> +	/*
>> +	 * All queues in a multi-queue group will use the primary queue
>> +	 * of the group to interface with GuC.
>> +	 */
>> +	q = xe_exec_queue_multi_queue_primary(q);
>> +
>>  	if (!exec_queue_enabled(q) && !exec_queue_suspended(q)) {
>>  		action[len++] = XE_GUC_ACTION_SCHED_CONTEXT_MODE_SET;
>>  		action[len++] = q->guc->id;
>> @@ -879,6 +1014,18 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job)
>>  	trace_xe_sched_job_run(job);
>>
>>  	if (!killed_or_banned_or_wedged && !xe_sched_job_is_error(job)) {
>> +		if (xe_exec_queue_is_multi_queue_secondary(q)) {
>> +			struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
>> +
>> +			if (exec_queue_killed_or_banned_or_wedged(primary)) {
>> +				killed_or_banned_or_wedged = true;
>> +				goto run_job_out;
>> +			}
>> +
>> +			if (!exec_queue_registered(primary))
>> +				register_exec_queue(primary, GUC_CONTEXT_NORMAL);
>> +		}
>> +
>>  		if (!exec_queue_registered(q))
>>  			register_exec_queue(q, GUC_CONTEXT_NORMAL);
>>  		if (!job->skip_emit)
>> @@ -887,6 +1034,7 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job)
>>  		job->skip_emit = false;
>>  	}
>>
>> +run_job_out:
>>  	/*
>>  	 * We don't care about job-fence ordering in LR VMs because these fences
>>  	 * are never exported; they are used solely to keep jobs on the pending
>> @@ -912,6 +1060,11 @@ int xe_guc_read_stopped(struct xe_guc *guc)
>>  	return atomic_read(&guc->submission_state.stopped);
>>  }
>>
>> +static void handle_multi_queue_secondary_sched_done(struct xe_guc *guc,
>> +						    struct xe_exec_queue *q,
>> +						    u32 runnable_state);
>> +static void handle_deregister_done(struct xe_guc *guc, struct xe_exec_queue *q);
>> +
>>  #define MAKE_SCHED_CONTEXT_ACTION(q, enable_disable)			\
>>  	u32 action[] = {						\
>>  		XE_GUC_ACTION_SCHED_CONTEXT_MODE_SET,			\
>> @@ -925,7 +1078,9 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
>>  	MAKE_SCHED_CONTEXT_ACTION(q, DISABLE);
>>  	int ret;
>>
>> -	set_min_preemption_timeout(guc, q);
>> +	if (!xe_exec_queue_is_multi_queue_secondary(q))
>> +		set_min_preemption_timeout(guc, q);
>> +
>>  	smp_rmb();
>>  	ret = wait_event_timeout(guc->ct.wq,
>>  				 (!exec_queue_pending_enable(q) &&
>> @@ -953,9 +1108,12 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
>>  	 * Reserve space for both G2H here as the 2nd G2H is sent from a G2H
>>  	 * handler and we are not allowed to reserved G2H space in handlers.
>>  	 */
>> -	xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
>> -		       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET +
>> -		       G2H_LEN_DW_DEREGISTER_CONTEXT, 2);
>> +	if (xe_exec_queue_is_multi_queue_secondary(q))
>> +		handle_multi_queue_secondary_sched_done(guc, q, 0);
>> +	else
>> +		xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
>> +			       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET +
>> +			       G2H_LEN_DW_DEREGISTER_CONTEXT, 2);
>>  }
>>
>>  static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
>> @@ -1161,8 +1319,11 @@ static void enable_scheduling(struct xe_exec_queue *q)
>>  	set_exec_queue_enabled(q);
>>  	trace_xe_exec_queue_scheduling_enable(q);
>>
>> -	xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
>> -		       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
>> +	if (xe_exec_queue_is_multi_queue_secondary(q))
>> +		handle_multi_queue_secondary_sched_done(guc, q, 1);
>> +	else
>> +		xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
>> +			       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
>>
>>  	ret = wait_event_timeout(guc->ct.wq,
>>  				 !exec_queue_pending_enable(q) ||
>> @@ -1186,14 +1347,17 @@ static void disable_scheduling(struct xe_exec_queue *q, bool immediate)
>>  	xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q));
>>  	xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_disable(q));
>>
>> -	if (immediate)
>> +	if (immediate && !xe_exec_queue_is_multi_queue_secondary(q))
>>  		set_min_preemption_timeout(guc, q);
>>  	clear_exec_queue_enabled(q);
>>  	set_exec_queue_pending_disable(q);
>>  	trace_xe_exec_queue_scheduling_disable(q);
>>
>> -	xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
>> -		       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
>> +	if (xe_exec_queue_is_multi_queue_secondary(q))
>> +		handle_multi_queue_secondary_sched_done(guc, q, 0);
>> +	else
>> +		xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
>> +			       G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
>>  }
>>
>>  static void __deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q)
>> @@ -1211,8 +1375,11 @@ static void __deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q)
>>  	set_exec_queue_destroyed(q);
>>  	trace_xe_exec_queue_deregister(q);
>>
>> -	xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
>> -		       G2H_LEN_DW_DEREGISTER_CONTEXT, 1);
>> +	if (xe_exec_queue_is_multi_queue_secondary(q))
>> +		handle_deregister_done(guc, q);
>> +	else
>> +		xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
>> +			       G2H_LEN_DW_DEREGISTER_CONTEXT, 1);
>>  }
>>
>>  static enum drm_gpu_sched_stat
>> @@ -1655,6 +1822,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
>>  {
>>  	struct xe_gpu_scheduler *sched;
>>  	struct xe_guc *guc = exec_queue_to_guc(q);
>> +	struct workqueue_struct *submit_wq = NULL;
>>  	struct xe_guc_exec_queue *ge;
>>  	long timeout;
>>  	int err, i;
>> @@ -1675,8 +1843,20 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
>>
>>  	timeout = (q->vm && xe_vm_in_lr_mode(q->vm)) ? MAX_SCHEDULE_TIMEOUT :
>>  		  msecs_to_jiffies(q->sched_props.job_timeout_ms);
>> +
>> +	/*
>> +	 * Use primary queue's submit_wq for all secondary queues of a
>> +	 * multi queue group. This serialization avoids any locking around
>> +	 * CGP synchronization with GuC.
>> +	 */
>> +	if (xe_exec_queue_is_multi_queue_secondary(q)) {
>> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
>> +
>> +		submit_wq = primary->guc->sched.base.submit_wq;
>> +	}
>> +
>>  	err = xe_sched_init(&ge->sched, &drm_sched_ops, &xe_sched_ops,
>> -			    NULL, xe_lrc_ring_size() / MAX_JOB_SIZE_BYTES, 64,
>> +			    submit_wq, xe_lrc_ring_size() / MAX_JOB_SIZE_BYTES, 64,
>>  			    timeout, guc_to_gt(guc)->ordered_wq, NULL,
>>  			    q->name, gt_to_xe(q->gt)->drm.dev);
>>  	if (err)
>> @@ -2413,7 +2593,11 @@ static void deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q)
>>
>>  	trace_xe_exec_queue_deregister(q);
>>
>> -	xe_guc_ct_send_g2h_handler(&guc->ct, action, ARRAY_SIZE(action));
>> +	if (xe_exec_queue_is_multi_queue_secondary(q))
>> +		handle_deregister_done(guc, q);
>> +	else
>> +		xe_guc_ct_send_g2h_handler(&guc->ct, action,
>> +					   ARRAY_SIZE(action));
>>  }
>>
>>  static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q,
>> @@ -2463,6 +2647,16 @@ static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q,
>>  	}
>>  }
>>
>> +static void handle_multi_queue_secondary_sched_done(struct xe_guc *guc,
>> +						    struct xe_exec_queue *q,
>> +						    u32 runnable_state)
>> +{
>> +	/* Take CT lock here as handle_sched_done() do send a h2g message */
>> +	mutex_lock(&guc->ct.lock);
>> +	handle_sched_done(guc, q, runnable_state);
>> +	mutex_unlock(&guc->ct.lock);
>> +}
>> +
>>  int xe_guc_sched_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
>>  {
>>  	struct xe_exec_queue *q;
>> @@ -2667,6 +2861,44 @@ int xe_guc_exec_queue_reset_failure_handler(struct xe_guc *guc, u32 *msg, u32 le
>>  	return 0;
>>  }
>>
>> +/**
>> + * xe_guc_exec_queue_cgp_sync_done_handler - CGP synchronization done handler
>> + * @guc: guc
>> + * @msg: message indicating CGP sync done
>> + * @len: length of message
>> + *
>> + * Set multi queue group's sync_pending flag to false and wakeup anyone waiting
>> + * for CGP synchronization to complete.
>> + *
>> + * Return: 0 on success, -EPROTO for malformed messages.
>> + */
>> +int xe_guc_exec_queue_cgp_sync_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
>> +{
>> +	struct xe_device *xe = guc_to_xe(guc);
>> +	struct xe_exec_queue *q;
>> +	u32 guc_id = msg[0];
>> +
>> +	if (unlikely(len < 1)) {
>> +		drm_err(&xe->drm, "Invalid CGP_SYNC_DONE length %u", len);
>> +		return -EPROTO;
>> +	}
>> +
>> +	q = g2h_exec_queue_lookup(guc, guc_id);
>> +	if (unlikely(!q))
>> +		return -EPROTO;
>> +
>> +	if (!xe_exec_queue_is_multi_queue_primary(q)) {
>> +		drm_err(&xe->drm, "Unexpected CGP_SYNC_DONE response");
>> +		return -EPROTO;
>> +	}
>> +
>> +	/* Wakeup the serialized cgp update wait */
>> +	WRITE_ONCE(q->multi_queue.group->sync_pending, false);
>> +	wake_up_all(&guc->ct.wq);
>
>We have helper for this now: xe_guc_ct_wake_waiters
>
>Still need to scrub the entire code for 'wake_up_all(&guc->ct.wq)' and
>fix those up but let's use this in new code.
>

Ok, will use the helper here.

Niranjana

>Other than these mirror nit, lgtm.
>
>Matt
>
>> +
>> +	return 0;
>> +}
>> +
>>  static void
>>  guc_exec_queue_wq_snapshot_capture(struct xe_exec_queue *q,
>>  				   struct xe_guc_submit_exec_queue_snapshot *snapshot)
>> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.h b/drivers/gpu/drm/xe/xe_guc_submit.h
>> index b49a2748ec46..abfa94bce391 100644
>> --- a/drivers/gpu/drm/xe/xe_guc_submit.h
>> +++ b/drivers/gpu/drm/xe/xe_guc_submit.h
>> @@ -34,6 +34,7 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg,
>>  					       u32 len);
>>  int xe_guc_exec_queue_reset_failure_handler(struct xe_guc *guc, u32 *msg, u32 len);
>>  int xe_guc_error_capture_handler(struct xe_guc *guc, u32 *msg, u32 len);
>> +int xe_guc_exec_queue_cgp_sync_done_handler(struct xe_guc *guc, u32 *msg, u32 len);
>>
>>  struct xe_guc_submit_exec_queue_snapshot *
>>  xe_guc_exec_queue_snapshot_capture(struct xe_exec_queue *q);
>> --
>> 2.43.0
>>

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

* Re: [PATCH v3 09/18] drm/xe/multi_queue: Handle tearing down of a multi queue
  2025-11-22  5:47   ` Matthew Brost
@ 2025-12-09  3:31     ` Niranjana Vishwanathapura
  0 siblings, 0 replies; 41+ messages in thread
From: Niranjana Vishwanathapura @ 2025-12-09  3:31 UTC (permalink / raw)
  To: Matthew Brost; +Cc: intel-xe

On Fri, Nov 21, 2025 at 09:47:10PM -0800, Matthew Brost wrote:
>On Thu, Nov 20, 2025 at 07:51:43PM -0800, Niranjana Vishwanathapura wrote:
>> As all queues of a multi queue group use the primary queue of the group
>> to interface with GuC. Hence there is a dependency between the queues of
>> the group. So, when primary queue of a multi queue group is cleaned up,
>> also trigger a cleanup of the secondary queues also. During cleanup, stop
>> and re-start submission for all queues of a multi queue group to avoid
>> any submission happening in parallel when a queue is being cleaned up.
>>
>> v2: Initialize group->list_lock, add fs_reclaim dependency, remove
>>     unwanted secondary queues cleanup (Matt Brost)
>> v3: Properly handle cleanup of multi-queue group (Matt Brost)
>>
>
>Also discussed privately, I believe the agreement is teardown the group
>on any individual job's timeout within the group. We maybe can leave
>this part out until my series here [1] merges to avoid a conflict with
>that series. Not huge deal as this feature won't be enabled for a bit as
>all supported platforms are behind force probe.
>

I have handled it in v4 of the patch series in a newly added patch.
drm/xe/multi_queue: Teardown group upon job timeout

Niranjana

>Matt
>
>[1] https://patchwork.freedesktop.org/series/155314/
>
>> Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
>> ---
>>  drivers/gpu/drm/xe/xe_exec_queue.c       |  10 ++
>>  drivers/gpu/drm/xe/xe_exec_queue_types.h |   6 +
>>  drivers/gpu/drm/xe/xe_guc_submit.c       | 154 ++++++++++++++++++-----
>>  3 files changed, 142 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
>> index cdc044d3c96c..ab161b74fef0 100644
>> --- a/drivers/gpu/drm/xe/xe_exec_queue.c
>> +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
>> @@ -87,6 +87,7 @@ static void xe_exec_queue_group_cleanup(struct xe_exec_queue *q)
>>  		xe_lrc_put(lrc);
>>
>>  	xa_destroy(&group->xa);
>> +	mutex_destroy(&group->list_lock);
>>  	xe_bo_unpin_map_no_vm(group->cgp_bo);
>>  	kfree(group);
>>  }
>> @@ -627,9 +628,18 @@ static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue *
>>
>>  	group->primary = q;
>>  	group->cgp_bo = bo;
>> +	INIT_LIST_HEAD(&group->list);
>>  	xa_init_flags(&group->xa, XA_FLAGS_ALLOC1);
>> +	mutex_init(&group->list_lock);
>>  	q->multi_queue.group = group;
>>
>> +	/* group->list_lock is used in submission backend */
>> +	if (!IS_ENABLED(CONFIG_LOCKDEP)) {
>> +		fs_reclaim_acquire(GFP_KERNEL);
>> +		might_lock(&group->list_lock);
>> +		fs_reclaim_release(GFP_KERNEL);
>> +	}
>> +
>>  	return 0;
>>  }
>>
>> diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> index cafb3ba9a123..5721fb4bad1a 100644
>> --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
>> @@ -58,6 +58,10 @@ struct xe_exec_queue_group {
>>  	struct xe_bo *cgp_bo;
>>  	/** @xa: xarray to store LRCs */
>>  	struct xarray xa;
>> +	/** @list: List of all secondary queues in the group */
>> +	struct list_head list;
>> +	/** @list_lock: Secondary queue list lock */
>> +	struct mutex list_lock;
>>  	/** @sync_pending: CGP_SYNC_DONE g2h response pending */
>>  	bool sync_pending;
>>  };
>> @@ -145,6 +149,8 @@ struct xe_exec_queue {
>>  	struct {
>>  		/** @multi_queue.group: Queue group information */
>>  		struct xe_exec_queue_group *group;
>> +		/** @multi_queue.link: Link into group's secondary queues list */
>> +		struct list_head link;
>>  		/** @multi_queue.priority: Queue priority within the multi-queue group */
>>  		enum xe_multi_queue_priority priority;
>>  		/** @multi_queue.pos: Position of queue within the multi-queue group */
>> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
>> index ce870a119800..2e5fff7ad69b 100644
>> --- a/drivers/gpu/drm/xe/xe_guc_submit.c
>> +++ b/drivers/gpu/drm/xe/xe_guc_submit.c
>> @@ -577,6 +577,45 @@ static bool vf_recovery(struct xe_guc *guc)
>>  	return xe_gt_recovery_pending(guc_to_gt(guc));
>>  }
>>
>> +static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
>> +{
>> +	struct xe_guc *guc = exec_queue_to_guc(q);
>> +	struct xe_device *xe = guc_to_xe(guc);
>> +
>> +	/** to wakeup xe_wait_user_fence ioctl if exec queue is reset */
>> +	wake_up_all(&xe->ufence_wq);
>> +
>> +	if (xe_exec_queue_is_lr(q))
>> +		queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr);
>> +	else
>> +		xe_sched_tdr_queue_imm(&q->guc->sched);
>> +}
>> +
>> +static void xe_guc_exec_queue_reset_trigger_cleanup(struct xe_exec_queue *q)
>> +{
>> +	if (xe_exec_queue_is_multi_queue(q)) {
>> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
>> +		struct xe_exec_queue_group *group = q->multi_queue.group;
>> +		struct xe_exec_queue *eq;
>> +
>> +		set_exec_queue_reset(primary);
>> +		if (!exec_queue_banned(primary) && !exec_queue_check_timeout(primary))
>> +			xe_guc_exec_queue_trigger_cleanup(primary);
>> +
>> +		mutex_lock(&group->list_lock);
>> +		list_for_each_entry(eq, &group->list, multi_queue.link) {
>> +			set_exec_queue_reset(eq);
>> +			if (!exec_queue_banned(eq) && !exec_queue_check_timeout(eq))
>> +				xe_guc_exec_queue_trigger_cleanup(eq);
>> +		}
>> +		mutex_unlock(&group->list_lock);
>> +	} else {
>> +		set_exec_queue_reset(q);
>> +		if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
>> +			xe_guc_exec_queue_trigger_cleanup(q);
>> +	}
>> +}
>> +
>>  #define parallel_read(xe_, map_, field_) \
>>  	xe_map_rd_field(xe_, &map_, 0, struct guc_submit_parallel_scratch, \
>>  			field_)
>> @@ -939,6 +978,50 @@ static void wq_item_append(struct xe_exec_queue *q)
>>  	parallel_write(xe, map, wq_desc.tail, q->guc->wqi_tail);
>>  }
>>
>> +static void xe_guc_exec_queue_submission_start(struct xe_exec_queue *q)
>> +{
>> +	/*
>> +	 * If the exec queue is part of a multi queue group, then start submission
>> +	 * on all queues of the multi queue group.
>> +	 */
>> +	if (xe_exec_queue_is_multi_queue(q)) {
>> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
>> +		struct xe_exec_queue_group *group = q->multi_queue.group;
>> +		struct xe_exec_queue *eq;
>> +
>> +		xe_sched_submission_start(&primary->guc->sched);
>> +
>> +		mutex_lock(&group->list_lock);
>> +		list_for_each_entry(eq, &group->list, multi_queue.link)
>> +			xe_sched_submission_start(&eq->guc->sched);
>> +		mutex_unlock(&group->list_lock);
>> +	} else {
>> +		xe_sched_submission_start(&q->guc->sched);
>> +	}
>> +}
>> +
>> +static void xe_guc_exec_queue_submission_stop(struct xe_exec_queue *q)
>> +{
>> +	/*
>> +	 * If the exec queue is part of a multi queue group, then stop submission
>> +	 * on all queues of the multi queue group.
>> +	 */
>> +	if (xe_exec_queue_is_multi_queue(q)) {
>> +		struct xe_exec_queue *primary = xe_exec_queue_multi_queue_primary(q);
>> +		struct xe_exec_queue_group *group = q->multi_queue.group;
>> +		struct xe_exec_queue *eq;
>> +
>> +		xe_sched_submission_stop(&primary->guc->sched);
>> +
>> +		mutex_lock(&group->list_lock);
>> +		list_for_each_entry(eq, &group->list, multi_queue.link)
>> +			xe_sched_submission_stop(&eq->guc->sched);
>> +		mutex_unlock(&group->list_lock);
>> +	} else {
>> +		xe_sched_submission_stop(&q->guc->sched);
>> +	}
>> +}
>> +
>>  #define RESUME_PENDING	~0x0ull
>>  static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job)
>>  {
>> @@ -1117,20 +1200,6 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
>>  			       G2H_LEN_DW_DEREGISTER_CONTEXT, 2);
>>  }
>>
>> -static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
>> -{
>> -	struct xe_guc *guc = exec_queue_to_guc(q);
>> -	struct xe_device *xe = guc_to_xe(guc);
>> -
>> -	/** to wakeup xe_wait_user_fence ioctl if exec queue is reset */
>> -	wake_up_all(&xe->ufence_wq);
>> -
>> -	if (xe_exec_queue_is_lr(q))
>> -		queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr);
>> -	else
>> -		xe_sched_tdr_queue_imm(&q->guc->sched);
>> -}
>> -
>>  /**
>>   * xe_guc_submit_wedge() - Wedge GuC submission
>>   * @guc: the GuC object
>> @@ -1204,8 +1273,12 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
>>  	if (!exec_queue_killed(q))
>>  		wedged = guc_submit_hint_wedged(exec_queue_to_guc(q));
>>
>> -	/* Kill the run_job / process_msg entry points */
>> -	xe_sched_submission_stop(sched);
>> +	/*
>> +	 * Kill the run_job / process_msg entry points.
>> +	 * As this function is serialized across exec queues, it is safe to
>> +	 * stop and restart submission on all queues of a multi queue group.
>> +	 */
>> +	xe_guc_exec_queue_submission_stop(q);
>>
>>  	/*
>>  	 * Engine state now mostly stable, disable scheduling / deregister if
>> @@ -1241,7 +1314,7 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
>>  				   q->guc->id);
>>  			xe_devcoredump(q, NULL, "Schedule disable failed to respond, guc_id=%d\n",
>>  				       q->guc->id);
>> -			xe_sched_submission_start(sched);
>> +			xe_guc_exec_queue_submission_start(q);
>>  			xe_gt_reset_async(q->gt);
>>  			return;
>>  		}
>> @@ -1252,7 +1325,7 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
>>
>>  	xe_hw_fence_irq_stop(q->fence_irq);
>>
>> -	xe_sched_submission_start(sched);
>> +	xe_guc_exec_queue_submission_start(q);
>>
>>  	spin_lock(&sched->base.job_list_lock);
>>  	list_for_each_entry(job, &sched->base.pending_list, drm.list)
>> @@ -1410,8 +1483,12 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
>>  	    vf_recovery(guc))
>>  		return DRM_GPU_SCHED_STAT_NO_HANG;
>>
>> -	/* Kill the run_job entry point */
>> -	xe_sched_submission_stop(sched);
>> +	/*
>> +	 * Kill the run_job entry point.
>> +	 * As this function is serialized across exec queues, it is safe to
>> +	 * stop and restart submission on all queues of a multi queue group.
>> +	 */
>> +	xe_guc_exec_queue_submission_stop(q);
>>
>>  	/* Must check all state after stopping scheduler */
>>  	skip_timeout_check = exec_queue_reset(q) ||
>> @@ -1568,7 +1645,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
>>  	 * fences that are complete
>>  	 */
>>  	xe_sched_add_pending_job(sched, job);
>> -	xe_sched_submission_start(sched);
>> +	xe_guc_exec_queue_submission_start(q);
>>
>>  	xe_guc_exec_queue_trigger_cleanup(q);
>>
>> @@ -1592,7 +1669,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
>>  	 * but there is not currently an easy way to do in DRM scheduler. With
>>  	 * some thought, do this in a follow up.
>>  	 */
>> -	xe_sched_submission_start(sched);
>> +	xe_guc_exec_queue_submission_start(q);
>>  handle_vf_resume:
>>  	return DRM_GPU_SCHED_STAT_NO_HANG;
>>  }
>> @@ -1623,6 +1700,14 @@ static void __guc_exec_queue_destroy_async(struct work_struct *w)
>>  	guard(xe_pm_runtime)(guc_to_xe(guc));
>>  	trace_xe_exec_queue_destroy(q);
>>
>> +	if (xe_exec_queue_is_multi_queue_secondary(q)) {
>> +		struct xe_exec_queue_group *group = q->multi_queue.group;
>> +
>> +		mutex_lock(&group->list_lock);
>> +		list_del(&q->multi_queue.link);
>> +		mutex_unlock(&group->list_lock);
>> +	}
>> +
>>  	if (xe_exec_queue_is_lr(q))
>>  		cancel_work_sync(&ge->lr_tdr);
>>  	/* Confirm no work left behind accessing device structures */
>> @@ -1913,6 +1998,19 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
>>
>>  	xe_exec_queue_assign_name(q, q->guc->id);
>>
>> +	/*
>> +	 * Maintain secondary queues of the multi queue group in a list
>> +	 * for handling dependencies across the queues in the group.
>> +	 */
>> +	if (xe_exec_queue_is_multi_queue_secondary(q)) {
>> +		struct xe_exec_queue_group *group = q->multi_queue.group;
>> +
>> +		INIT_LIST_HEAD(&q->multi_queue.link);
>> +		mutex_lock(&group->list_lock);
>> +		list_add_tail(&q->multi_queue.link, &group->list);
>> +		mutex_unlock(&group->list_lock);
>> +	}
>> +
>>  	trace_xe_exec_queue_create(q);
>>
>>  	return 0;
>> @@ -2140,6 +2238,10 @@ static void guc_exec_queue_resume(struct xe_exec_queue *q)
>>
>>  static bool guc_exec_queue_reset_status(struct xe_exec_queue *q)
>>  {
>> +	if (xe_exec_queue_is_multi_queue_secondary(q) &&
>> +	    guc_exec_queue_reset_status(xe_exec_queue_multi_queue_primary(q)))
>> +		return true;
>> +
>>  	return exec_queue_reset(q) || exec_queue_killed_or_banned_or_wedged(q);
>>  }
>>
>> @@ -2801,9 +2903,7 @@ int xe_guc_exec_queue_reset_handler(struct xe_guc *guc, u32 *msg, u32 len)
>>  	 * jobs by setting timeout of the job to the minimum value kicking
>>  	 * guc_exec_queue_timedout_job.
>>  	 */
>> -	set_exec_queue_reset(q);
>> -	if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
>> -		xe_guc_exec_queue_trigger_cleanup(q);
>> +	xe_guc_exec_queue_reset_trigger_cleanup(q);
>>
>>  	return 0;
>>  }
>> @@ -2882,9 +2982,7 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg,
>>  	trace_xe_exec_queue_memory_cat_error(q);
>>
>>  	/* Treat the same as engine reset */
>> -	set_exec_queue_reset(q);
>> -	if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
>> -		xe_guc_exec_queue_trigger_cleanup(q);
>> +	xe_guc_exec_queue_reset_trigger_cleanup(q);
>>
>>  	return 0;
>>  }
>> --
>> 2.43.0
>>

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

end of thread, other threads:[~2025-12-09  3:31 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-21  3:51 [PATCH v3 00/18] drm/xe: Multi Queue feature support Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 01/18] drm/xe/multi_queue: Add multi_queue_enable_mask to gt information Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 02/18] drm/xe/multi_queue: Add user interface for multi queue support Niranjana Vishwanathapura
2025-11-21 22:51   ` Matthew Brost
2025-11-22  4:35     ` Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 03/18] drm/xe/multi_queue: Add GuC " Niranjana Vishwanathapura
2025-11-22 22:16   ` Matthew Brost
2025-12-03  3:40     ` Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 04/18] drm/xe/multi_queue: Add multi queue priority property Niranjana Vishwanathapura
2025-11-21 22:57   ` Matthew Brost
2025-11-21  3:51 ` [PATCH v3 05/18] drm/xe/multi_queue: Handle invalid exec queue property setting Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 06/18] drm/xe/multi_queue: Add exec_queue set_property ioctl support Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 07/18] drm/xe/multi_queue: Add support for multi queue dynamic priority change Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 08/18] drm/xe/multi_queue: Add multi queue information to guc_info dump Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 09/18] drm/xe/multi_queue: Handle tearing down of a multi queue Niranjana Vishwanathapura
2025-11-21 23:03   ` Matthew Brost
2025-11-22  4:40     ` Niranjana Vishwanathapura
2025-11-22  5:47   ` Matthew Brost
2025-12-09  3:31     ` Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 10/18] drm/xe/multi_queue: Set QUEUE_DRAIN_MODE for Multi Queue batches Niranjana Vishwanathapura
2025-11-24 18:49   ` Matt Roper
2025-12-02 21:28     ` Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 11/18] drm/xe/multi_queue: Handle CGP context error Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 12/18] drm/xe/multi_queue: Reset GT upon CGP_SYNC failure Niranjana Vishwanathapura
2025-11-21 23:08   ` Matthew Brost
2025-11-21  3:51 ` [PATCH v3 13/18] drm/xe/multi_queue: Tracepoint support Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 14/18] drm/xe/multi_queue: Support active group after primary is destroyed Niranjana Vishwanathapura
2025-11-22  5:57   ` Matthew Brost
2025-11-22  6:08     ` Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 15/18] drm/xe/xe3p: Disable GuC Dynamic ICS for Xe3p Niranjana Vishwanathapura
2025-11-21  3:51 ` [PATCH v3 16/18] drm/xe/doc: Add documentation for Multi Queue Group Niranjana Vishwanathapura
2025-11-22  6:02   ` Matthew Brost
2025-11-21  3:51 ` [PATCH v3 17/18] drm/xe/doc: Add documentation for Multi Queue Group GuC interface Niranjana Vishwanathapura
2025-11-22  6:10   ` Matthew Brost
2025-11-21  3:51 ` [PATCH v3 18/18] drm/xe/multi_queue: Enable multi_queue on xe3p_xpc Niranjana Vishwanathapura
2025-11-21  4:01 ` ✗ CI.checkpatch: warning for drm/xe: Multi Queue feature support (rev3) Patchwork
2025-11-21  4:02 ` ✓ CI.KUnit: success " Patchwork
2025-11-21  4:51 ` ✗ Xe.CI.BAT: failure " Patchwork
2025-11-21  8:10 ` ✗ Xe.CI.Full: " Patchwork
2025-11-24 14:04 ` Patchwork
2025-11-27  9:38 ` [PATCH v3 00/18] drm/xe: Multi Queue feature support Hoppe, Mateusz

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