Commit 535c445e authored by Matthew Brost's avatar Matthew Brost
Browse files

drm/xe: Add dependency scheduler for GT TLB invalidations to bind queues



Add a generic dependency scheduler for GT TLB invalidations, used to
schedule jobs that issue GT TLB invalidations to bind queues.

v2:
 - Use shared GT TLB invalidation queue for dep scheduler
 - Break allocation of dep scheduler into its own function
 - Add define for max number tlb invalidations
 - Skip media if not present

Suggested-by: default avatarThomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: default avatarMatthew Brost <matthew.brost@intel.com>
Reviewed-by: default avatarStuart Summers <stuart.summers@intel.com>
Link: https://lore.kernel.org/r/20250724191216.4076566-5-matthew.brost@intel.com
parent ada51219
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <drm/drm_file.h>
#include <uapi/drm/xe_drm.h>

#include "xe_dep_scheduler.h"
#include "xe_device.h"
#include "xe_gt.h"
#include "xe_hw_engine_class_sysfs.h"
@@ -39,6 +40,12 @@ static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue

static void __xe_exec_queue_free(struct xe_exec_queue *q)
{
	int i;

	for (i = 0; i < XE_EXEC_QUEUE_TLB_INVAL_COUNT; ++i)
		if (q->tlb_inval[i].dep_scheduler)
			xe_dep_scheduler_fini(q->tlb_inval[i].dep_scheduler);

	if (xe_exec_queue_uses_pxp(q))
		xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q);
	if (q->vm)
@@ -50,6 +57,39 @@ static void __xe_exec_queue_free(struct xe_exec_queue *q)
	kfree(q);
}

static int alloc_dep_schedulers(struct xe_device *xe, struct xe_exec_queue *q)
{
	struct xe_tile *tile = gt_to_tile(q->gt);
	int i;

	for (i = 0; i < XE_EXEC_QUEUE_TLB_INVAL_COUNT; ++i) {
		struct xe_dep_scheduler *dep_scheduler;
		struct xe_gt *gt;
		struct workqueue_struct *wq;

		if (i == XE_EXEC_QUEUE_TLB_INVAL_PRIMARY_GT)
			gt = tile->primary_gt;
		else
			gt = tile->media_gt;

		if (!gt)
			continue;

		wq = gt->tlb_invalidation.job_wq;

#define MAX_TLB_INVAL_JOBS	16	/* Picking a reasonable value */
		dep_scheduler = xe_dep_scheduler_create(xe, wq, q->name,
							MAX_TLB_INVAL_JOBS);
		if (IS_ERR(dep_scheduler))
			return PTR_ERR(dep_scheduler);

		q->tlb_inval[i].dep_scheduler = dep_scheduler;
	}
#undef MAX_TLB_INVAL_JOBS

	return 0;
}

static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
						   struct xe_vm *vm,
						   u32 logical_mask,
@@ -94,6 +134,14 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
	else
		q->sched_props.priority = XE_EXEC_QUEUE_PRIORITY_NORMAL;

	if (q->flags & (EXEC_QUEUE_FLAG_MIGRATE | EXEC_QUEUE_FLAG_VM)) {
		err = alloc_dep_schedulers(xe, q);
		if (err) {
			__xe_exec_queue_free(q);
			return ERR_PTR(err);
		}
	}

	if (vm)
		q->vm = xe_vm_get(vm);

+13 −0
Original line number Diff line number Diff line
@@ -134,6 +134,19 @@ struct xe_exec_queue {
		struct list_head link;
	} lr;

#define XE_EXEC_QUEUE_TLB_INVAL_PRIMARY_GT	0
#define XE_EXEC_QUEUE_TLB_INVAL_MEDIA_GT	1
#define XE_EXEC_QUEUE_TLB_INVAL_COUNT		(XE_EXEC_QUEUE_TLB_INVAL_MEDIA_GT  + 1)

	/** @tlb_inval: TLB invalidations exec queue state */
	struct {
		/**
		 * @tlb_inval.dep_scheduler: The TLB invalidation
		 * dependency scheduler
		 */
		struct xe_dep_scheduler *dep_scheduler;
	} tlb_inval[XE_EXEC_QUEUE_TLB_INVAL_COUNT];

	/** @pxp: PXP info tracking */
	struct {
		/** @pxp.type: PXP session type used by this queue */