Unverified Commit ae5fbbda authored by Daniele Ceraolo Spurio's avatar Daniele Ceraolo Spurio Committed by Rodrigo Vivi
Browse files

drm/xe: Fix error handling if PXP fails to start



Since the PXP start comes after __xe_exec_queue_init() has completed,
we need to cleanup what was done in that function in case of a PXP
start error.
__xe_exec_queue_init calls the submission backend init() function,
so we need to introduce an opposite for that. Unfortunately, while
we already have a fini() function pointer, it performs other
operations in addition to cleaning up what was done by the init().
Therefore, for clarity, the existing fini() has been renamed to
destroy(), while a new fini() has been added to only clean up what was
done by the init(), with the latter being called by the former (via
xe_exec_queue_fini).

Fixes: 72d47960 ("drm/xe/pxp/uapi: Add userspace and LRC support for PXP-using queues")
Signed-off-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Signed-off-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Link: https://lore.kernel.org/r/20250909221240.3711023-3-daniele.ceraolospurio@intel.com


(cherry picked from commit 62666732)
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent ff89a4d2
Loading
Loading
Loading
Loading
+15 −7
Original line number Diff line number Diff line
@@ -151,6 +151,16 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q)
	return err;
}

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

	q->ops->fini(q);

	for (i = 0; i < q->width; ++i)
		xe_lrc_put(q->lrc[i]);
}

struct xe_exec_queue *xe_exec_queue_create(struct xe_device *xe, struct xe_vm *vm,
					   u32 logical_mask, u16 width,
					   struct xe_hw_engine *hwe, u32 flags,
@@ -181,11 +191,13 @@ struct xe_exec_queue *xe_exec_queue_create(struct xe_device *xe, struct xe_vm *v
	if (xe_exec_queue_uses_pxp(q)) {
		err = xe_pxp_exec_queue_add(xe->pxp, q);
		if (err)
			goto err_post_alloc;
			goto err_post_init;
	}

	return q;

err_post_init:
	__xe_exec_queue_fini(q);
err_post_alloc:
	__xe_exec_queue_free(q);
	return ERR_PTR(err);
@@ -283,13 +295,11 @@ void xe_exec_queue_destroy(struct kref *ref)
			xe_exec_queue_put(eq);
	}

	q->ops->fini(q);
	q->ops->destroy(q);
}

void xe_exec_queue_fini(struct xe_exec_queue *q)
{
	int i;

	/*
	 * Before releasing our ref to lrc and xef, accumulate our run ticks
	 * and wakeup any waiters.
@@ -298,9 +308,7 @@ void xe_exec_queue_fini(struct xe_exec_queue *q)
	if (q->xef && atomic_dec_and_test(&q->xef->exec_queue.pending_removal))
		wake_up_var(&q->xef->exec_queue.pending_removal);

	for (i = 0; i < q->width; ++i)
		xe_lrc_put(q->lrc[i]);

	__xe_exec_queue_fini(q);
	__xe_exec_queue_free(q);
}

+7 −1
Original line number Diff line number Diff line
@@ -166,8 +166,14 @@ struct xe_exec_queue_ops {
	int (*init)(struct xe_exec_queue *q);
	/** @kill: Kill inflight submissions for backend */
	void (*kill)(struct xe_exec_queue *q);
	/** @fini: Fini exec queue for submission backend */
	/** @fini: Undoes the init() for submission backend */
	void (*fini)(struct xe_exec_queue *q);
	/**
	 * @destroy: Destroy exec queue for submission backend. The backend
	 * function must call xe_exec_queue_fini() (which will in turn call the
	 * fini() backend function) to ensure the queue is properly cleaned up.
	 */
	void (*destroy)(struct xe_exec_queue *q);
	/** @set_priority: Set priority for exec queue */
	int (*set_priority)(struct xe_exec_queue *q,
			    enum xe_exec_queue_priority priority);
+16 −9
Original line number Diff line number Diff line
@@ -385,10 +385,20 @@ static int execlist_exec_queue_init(struct xe_exec_queue *q)
	return err;
}

static void execlist_exec_queue_fini_async(struct work_struct *w)
static void execlist_exec_queue_fini(struct xe_exec_queue *q)
{
	struct xe_execlist_exec_queue *exl = q->execlist;

	drm_sched_entity_fini(&exl->entity);
	drm_sched_fini(&exl->sched);

	kfree(exl);
}

static void execlist_exec_queue_destroy_async(struct work_struct *w)
{
	struct xe_execlist_exec_queue *ee =
		container_of(w, struct xe_execlist_exec_queue, fini_async);
		container_of(w, struct xe_execlist_exec_queue, destroy_async);
	struct xe_exec_queue *q = ee->q;
	struct xe_execlist_exec_queue *exl = q->execlist;
	struct xe_device *xe = gt_to_xe(q->gt);
@@ -401,10 +411,6 @@ static void execlist_exec_queue_fini_async(struct work_struct *w)
		list_del(&exl->active_link);
	spin_unlock_irqrestore(&exl->port->lock, flags);

	drm_sched_entity_fini(&exl->entity);
	drm_sched_fini(&exl->sched);
	kfree(exl);

	xe_exec_queue_fini(q);
}

@@ -413,10 +419,10 @@ static void execlist_exec_queue_kill(struct xe_exec_queue *q)
	/* NIY */
}

static void execlist_exec_queue_fini(struct xe_exec_queue *q)
static void execlist_exec_queue_destroy(struct xe_exec_queue *q)
{
	INIT_WORK(&q->execlist->fini_async, execlist_exec_queue_fini_async);
	queue_work(system_unbound_wq, &q->execlist->fini_async);
	INIT_WORK(&q->execlist->destroy_async, execlist_exec_queue_destroy_async);
	queue_work(system_unbound_wq, &q->execlist->destroy_async);
}

static int execlist_exec_queue_set_priority(struct xe_exec_queue *q,
@@ -467,6 +473,7 @@ static const struct xe_exec_queue_ops execlist_exec_queue_ops = {
	.init = execlist_exec_queue_init,
	.kill = execlist_exec_queue_kill,
	.fini = execlist_exec_queue_fini,
	.destroy = execlist_exec_queue_destroy,
	.set_priority = execlist_exec_queue_set_priority,
	.set_timeslice = execlist_exec_queue_set_timeslice,
	.set_preempt_timeout = execlist_exec_queue_set_preempt_timeout,
+1 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ struct xe_execlist_exec_queue {

	bool has_run;

	struct work_struct fini_async;
	struct work_struct destroy_async;

	enum xe_exec_queue_priority active_priority;
	struct list_head active_link;
+2 −2
Original line number Diff line number Diff line
@@ -35,8 +35,8 @@ struct xe_guc_exec_queue {
	struct xe_sched_msg static_msgs[MAX_STATIC_MSG_TYPE];
	/** @lr_tdr: long running TDR worker */
	struct work_struct lr_tdr;
	/** @fini_async: do final fini async from this worker */
	struct work_struct fini_async;
	/** @destroy_async: do final destroy async from this worker */
	struct work_struct destroy_async;
	/** @resume_time: time of last resume */
	u64 resume_time;
	/** @state: GuC specific state for this xe_exec_queue */
Loading