diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_breadcrumbs.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_breadcrumbs.c | 23 | 
1 files changed, 12 insertions, 11 deletions
| diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 48e1ba01ccf8..bcbc7abe6693 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -186,7 +186,7 @@ void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine)  	struct intel_wait *wait, *n, *first;  	if (!b->irq_armed) -		return; +		goto wakeup_signaler;  	/* We only disarm the irq when we are idle (all requests completed),  	 * so if the bottom-half remains asleep, it missed the request @@ -208,6 +208,14 @@ void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine)  	b->waiters = RB_ROOT;  	spin_unlock_irq(&b->rb_lock); + +	/* +	 * The signaling thread may be asleep holding a reference to a request, +	 * that had its signaling cancelled prior to being preempted. We need +	 * to kick the signaler, just in case, to release any such reference. +	 */ +wakeup_signaler: +	wake_up_process(b->signaler);  }  static bool use_fake_irq(const struct intel_breadcrumbs *b) @@ -517,6 +525,7 @@ static void __intel_engine_remove_wait(struct intel_engine_cs *engine,  	GEM_BUG_ON(RB_EMPTY_NODE(&wait->node));  	rb_erase(&wait->node, &b->waiters); +	RB_CLEAR_NODE(&wait->node);  out:  	GEM_BUG_ON(b->irq_wait == wait); @@ -650,23 +659,15 @@ static int intel_breadcrumbs_signaler(void *arg)  		}  		if (unlikely(do_schedule)) { -			DEFINE_WAIT(exec); -  			if (kthread_should_park())  				kthread_parkme(); -			if (kthread_should_stop()) { -				GEM_BUG_ON(request); +			if (unlikely(kthread_should_stop())) { +				i915_gem_request_put(request);  				break;  			} -			if (request) -				add_wait_queue(&request->execute, &exec); -  			schedule(); - -			if (request) -				remove_wait_queue(&request->execute, &exec);  		}  		i915_gem_request_put(request);  	} while (1); |