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: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Stuart Summers <stuart.summers@intel.com>
Link: https://lore.kernel.org/r/20250724191216.4076566-5-matthew.brost@intel.com
This commit is contained in:
Matthew Brost 2025-07-24 12:12:13 -07:00
parent ada5121948
commit 535c445eb9
2 changed files with 61 additions and 0 deletions

View File

@ -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);

View File

@ -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 */