diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_request.c')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_request.c | 114 | 
1 files changed, 89 insertions, 25 deletions
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index bbd71af00a91..765bec89fc0d 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -300,11 +300,11 @@ void i915_request_retire_upto(struct i915_request *rq)  }  static int -__i915_request_await_execution(struct i915_request *rq, -			       struct i915_request *signal, -			       void (*hook)(struct i915_request *rq, -					    struct dma_fence *signal), -			       gfp_t gfp) +__await_execution(struct i915_request *rq, +		  struct i915_request *signal, +		  void (*hook)(struct i915_request *rq, +			       struct dma_fence *signal), +		  gfp_t gfp)  {  	struct execute_cb *cb; @@ -341,6 +341,8 @@ __i915_request_await_execution(struct i915_request *rq,  	}  	spin_unlock_irq(&signal->lock); +	/* Copy across semaphore status as we need the same behaviour */ +	rq->sched.flags |= signal->sched.flags;  	return 0;  } @@ -811,31 +813,21 @@ already_busywaiting(struct i915_request *rq)  }  static int -emit_semaphore_wait(struct i915_request *to, -		    struct i915_request *from, -		    gfp_t gfp) +__emit_semaphore_wait(struct i915_request *to, +		      struct i915_request *from, +		      u32 seqno)  {  	const int has_token = INTEL_GEN(to->i915) >= 12;  	u32 hwsp_offset; -	int len; +	int len, err;  	u32 *cs;  	GEM_BUG_ON(INTEL_GEN(to->i915) < 8); -	/* Just emit the first semaphore we see as request space is limited. */ -	if (already_busywaiting(to) & from->engine->mask) -		goto await_fence; - -	if (i915_request_await_start(to, from) < 0) -		goto await_fence; - -	/* Only submit our spinner after the signaler is running! */ -	if (__i915_request_await_execution(to, from, NULL, gfp)) -		goto await_fence; -  	/* We need to pin the signaler's HWSP until we are finished reading. */ -	if (intel_timeline_read_hwsp(from, to, &hwsp_offset)) -		goto await_fence; +	err = intel_timeline_read_hwsp(from, to, &hwsp_offset); +	if (err) +		return err;  	len = 4;  	if (has_token) @@ -858,7 +850,7 @@ emit_semaphore_wait(struct i915_request *to,  		 MI_SEMAPHORE_POLL |  		 MI_SEMAPHORE_SAD_GTE_SDD) +  		has_token; -	*cs++ = from->fence.seqno; +	*cs++ = seqno;  	*cs++ = hwsp_offset;  	*cs++ = 0;  	if (has_token) { @@ -867,6 +859,28 @@ emit_semaphore_wait(struct i915_request *to,  	}  	intel_ring_advance(to, cs); +	return 0; +} + +static int +emit_semaphore_wait(struct i915_request *to, +		    struct i915_request *from, +		    gfp_t gfp) +{ +	/* Just emit the first semaphore we see as request space is limited. */ +	if (already_busywaiting(to) & from->engine->mask) +		goto await_fence; + +	if (i915_request_await_start(to, from) < 0) +		goto await_fence; + +	/* Only submit our spinner after the signaler is running! */ +	if (__await_execution(to, from, NULL, gfp)) +		goto await_fence; + +	if (__emit_semaphore_wait(to, from, from->fence.seqno)) +		goto await_fence; +  	to->sched.semaphores |= from->engine->mask;  	to->sched.flags |= I915_SCHED_HAS_SEMAPHORE_CHAIN;  	return 0; @@ -980,6 +994,57 @@ i915_request_await_dma_fence(struct i915_request *rq, struct dma_fence *fence)  	return 0;  } +static bool intel_timeline_sync_has_start(struct intel_timeline *tl, +					  struct dma_fence *fence) +{ +	return __intel_timeline_sync_is_later(tl, +					      fence->context, +					      fence->seqno - 1); +} + +static int intel_timeline_sync_set_start(struct intel_timeline *tl, +					 const struct dma_fence *fence) +{ +	return __intel_timeline_sync_set(tl, fence->context, fence->seqno - 1); +} + +static int +__i915_request_await_execution(struct i915_request *to, +			       struct i915_request *from, +			       void (*hook)(struct i915_request *rq, +					    struct dma_fence *signal)) +{ +	int err; + +	/* Submit both requests at the same time */ +	err = __await_execution(to, from, hook, I915_FENCE_GFP); +	if (err) +		return err; + +	/* Squash repeated depenendices to the same timelines */ +	if (intel_timeline_sync_has_start(i915_request_timeline(to), +					  &from->fence)) +		return 0; + +	/* Ensure both start together [after all semaphores in signal] */ +	if (intel_engine_has_semaphores(to->engine)) +		err = __emit_semaphore_wait(to, from, from->fence.seqno - 1); +	else +		err = i915_request_await_start(to, from); +	if (err < 0) +		return err; + +	/* Couple the dependency tree for PI on this exposed to->fence */ +	if (to->engine->schedule) { +		err = i915_sched_node_add_dependency(&to->sched, &from->sched); +		if (err < 0) +			return err; +	} + +	return intel_timeline_sync_set_start(i915_request_timeline(to), +					     &from->fence); +} +  int  i915_request_await_execution(struct i915_request *rq,  			     struct dma_fence *fence, @@ -1013,8 +1078,7 @@ i915_request_await_execution(struct i915_request *rq,  		if (dma_fence_is_i915(fence))  			ret = __i915_request_await_execution(rq,  							     to_request(fence), -							     hook, -							     I915_FENCE_GFP); +							     hook);  		else  			ret = i915_sw_fence_await_dma_fence(&rq->submit, fence,  							    I915_FENCE_TIMEOUT,  | 
