[Intel-gfx] [PATCH 18/57] drm/i915: Extract the ability to defer and rerun a request later

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Tue Feb 2 13:18:53 UTC 2021


On 01/02/2021 08:56, Chris Wilson wrote:
> Lift the ability to defer a request until later from execlists into the
> common layer.
> 
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> ---
>   .../drm/i915/gt/intel_execlists_submission.c  | 57 +++--------------
>   drivers/gpu/drm/i915/i915_scheduler.c         | 63 +++++++++++++++++--
>   drivers/gpu/drm/i915/i915_scheduler.h         |  5 +-
>   3 files changed, 67 insertions(+), 58 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
> index 853021314786..b56e321ef003 100644
> --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
> +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
> @@ -978,54 +978,6 @@ static void virtual_xfer_context(struct virtual_engine *ve,
>   	}
>   }
>   
> -static void defer_request(struct i915_request *rq, struct list_head * const pl)
> -{
> -	LIST_HEAD(list);
> -
> -	/*
> -	 * We want to move the interrupted request to the back of
> -	 * the round-robin list (i.e. its priority level), but
> -	 * in doing so, we must then move all requests that were in
> -	 * flight and were waiting for the interrupted request to
> -	 * be run after it again.
> -	 */
> -	do {
> -		struct i915_dependency *p;
> -
> -		GEM_BUG_ON(i915_request_is_active(rq));
> -		list_move_tail(&rq->sched.link, pl);
> -
> -		for_each_waiter(p, rq) {
> -			struct i915_request *w =
> -				container_of(p->waiter, typeof(*w), sched);
> -
> -			if (p->flags & I915_DEPENDENCY_WEAK)
> -				continue;
> -
> -			/* Leave semaphores spinning on the other engines */
> -			if (w->engine != rq->engine)
> -				continue;
> -
> -			/* No waiter should start before its signaler */
> -			GEM_BUG_ON(i915_request_has_initial_breadcrumb(w) &&
> -				   __i915_request_has_started(w) &&
> -				   !__i915_request_is_complete(rq));
> -
> -			if (!i915_request_is_ready(w))
> -				continue;
> -
> -			if (rq_prio(w) < rq_prio(rq))
> -				continue;
> -
> -			GEM_BUG_ON(rq_prio(w) > rq_prio(rq));
> -			GEM_BUG_ON(i915_request_is_active(w));
> -			list_move_tail(&w->sched.link, &list);
> -		}
> -
> -		rq = list_first_entry_or_null(&list, typeof(*rq), sched.link);
> -	} while (rq);
> -}
> -
>   static void defer_active(struct intel_engine_cs *engine)
>   {
>   	struct i915_request *rq;
> @@ -1034,7 +986,14 @@ static void defer_active(struct intel_engine_cs *engine)
>   	if (!rq)
>   		return;
>   
> -	defer_request(rq, i915_sched_lookup_priolist(engine, rq_prio(rq)));
> +	/*
> +	 * We want to move the interrupted request to the back of
> +	 * the round-robin list (i.e. its priority level), but
> +	 * in doing so, we must then move all requests that were in
> +	 * flight and were waiting for the interrupted request to
> +	 * be run after it again.
> +	 */
> +	__i915_sched_defer_request(engine, rq);
>   }
>   
>   static bool
> diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
> index 351c0c0055b5..bfd37ee801fd 100644
> --- a/drivers/gpu/drm/i915/i915_scheduler.c
> +++ b/drivers/gpu/drm/i915/i915_scheduler.c
> @@ -179,8 +179,8 @@ static void assert_priolists(struct intel_engine_execlists * const execlists)
>   	}
>   }
>   
> -struct list_head *
> -i915_sched_lookup_priolist(struct intel_engine_cs *engine, int prio)
> +static struct list_head *
> +lookup_priolist(struct intel_engine_cs *engine, int prio)
>   {
>   	struct intel_engine_execlists * const execlists = &engine->execlists;
>   	struct i915_priolist *p;
> @@ -332,7 +332,7 @@ static void __i915_request_set_priority(struct i915_request *rq, int prio)
>   	struct list_head *pos = &rq->sched.signalers_list;
>   	struct list_head *plist;
>   
> -	plist = i915_sched_lookup_priolist(engine, prio);
> +	plist = lookup_priolist(engine, prio);
>   
>   	/*
>   	 * Recursively bump all dependent priorities to match the new request.
> @@ -463,12 +463,63 @@ void i915_request_set_priority(struct i915_request *rq, int prio)
>   	spin_unlock_irqrestore(&engine->active.lock, flags);
>   }
>   
> +void __i915_sched_defer_request(struct intel_engine_cs *engine,
> +				struct i915_request *rq)
> +{
> +	struct list_head *pl;
> +	LIST_HEAD(list);
> +
> +	lockdep_assert_held(&engine->active.lock);
> +	GEM_BUG_ON(!test_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags));
> +
> +	/*
> +	 * When we defer a request, we must maintain its order with respect
> +	 * to those that are waiting upon it. So we traverse its chain of
> +	 * waiters and move any that are earlier than the request to after it.
> +	 */
> +	pl = lookup_priolist(engine, rq_prio(rq));
> +	do {
> +		struct i915_dependency *p;
> +
> +		GEM_BUG_ON(i915_request_is_active(rq));
> +		list_move_tail(&rq->sched.link, pl);
> +
> +		for_each_waiter(p, rq) {
> +			struct i915_request *w =
> +				container_of(p->waiter, typeof(*w), sched);
> +
> +			if (p->flags & I915_DEPENDENCY_WEAK)
> +				continue;
> +
> +			/* Leave semaphores spinning on the other engines */
> +			if (w->engine != engine)
> +				continue;
> +
> +			/* No waiter should start before its signaler */
> +			GEM_BUG_ON(i915_request_has_initial_breadcrumb(w) &&
> +				   __i915_request_has_started(w) &&
> +				   !__i915_request_is_complete(rq));
> +
> +			if (!i915_request_is_ready(w))
> +				continue;
> +
> +			if (rq_prio(w) < rq_prio(rq))
> +				continue;
> +
> +			GEM_BUG_ON(rq_prio(w) > rq_prio(rq));
> +			GEM_BUG_ON(i915_request_is_active(w));
> +			list_move_tail(&w->sched.link, &list);
> +		}
> +
> +		rq = list_first_entry_or_null(&list, typeof(*rq), sched.link);
> +	} while (rq);
> +}
> +
>   static void queue_request(struct intel_engine_cs *engine,
>   			  struct i915_request *rq)
>   {
>   	GEM_BUG_ON(!list_empty(&rq->sched.link));
> -	list_add_tail(&rq->sched.link,
> -		      i915_sched_lookup_priolist(engine, rq_prio(rq)));
> +	list_add_tail(&rq->sched.link, lookup_priolist(engine, rq_prio(rq)));
>   	set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
>   }
>   
> @@ -567,7 +618,7 @@ __i915_sched_rewind_requests(struct intel_engine_cs *engine)
>   		GEM_BUG_ON(rq_prio(rq) == I915_PRIORITY_INVALID);
>   		if (rq_prio(rq) != prio) {
>   			prio = rq_prio(rq);
> -			pl = i915_sched_lookup_priolist(engine, prio);
> +			pl = lookup_priolist(engine, prio);
>   		}
>   		GEM_BUG_ON(RB_EMPTY_ROOT(&engine->execlists.queue.rb_root));
>   
> diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h
> index 9860459fedb1..00ce0a9d519d 100644
> --- a/drivers/gpu/drm/i915/i915_scheduler.h
> +++ b/drivers/gpu/drm/i915/i915_scheduler.h
> @@ -44,6 +44,8 @@ void i915_request_enqueue(struct i915_request *request);
>   
>   struct i915_request *
>   __i915_sched_rewind_requests(struct intel_engine_cs *engine);
> +void __i915_sched_defer_request(struct intel_engine_cs *engine,
> +				struct i915_request *request);
>   
>   bool __i915_sched_suspend_request(struct intel_engine_cs *engine,
>   				  struct i915_request *rq);
> @@ -55,9 +57,6 @@ bool i915_sched_suspend_request(struct intel_engine_cs *engine,
>   void i915_sched_resume_request(struct intel_engine_cs *engine,
>   			       struct i915_request *rq);
>   
> -struct list_head *
> -i915_sched_lookup_priolist(struct intel_engine_cs *engine, int prio);
> -
>   void __i915_priolist_free(struct i915_priolist *p);
>   static inline void i915_priolist_free(struct i915_priolist *p)
>   {
> 

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>

Regards,

Tvrtko


More information about the Intel-gfx mailing list