On Mon, Nov 02, 2015 at 03:28:22PM +0000, Chris Wilson wrote: > That should keep the worker alive for a further 10 jiffies, hopefully > long enough for the next wait to occur. The cost is that it keeps the > interrupt asserted (and to avoid that requires a little rearrangment and > probably a dedicated kthread for each ring). Slightly better version that avoids keeping the interrupt active when not required: diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8d1e0a5e19a1..3e810c9ea3cb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1148,7 +1148,7 @@ static int __i915_spin_request(struct drm_i915_gem_request *req) { unsigned long timeout; - if (i915_gem_request_get_ring(req)->irq_refcount) + if (waitqueue_active(&i915_gem_request_get_ring(req)->irq_queue)) return -EBUSY; if (req->ring->seqno_barrier) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 21017daecb90..9ed063a85c05 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -68,9 +68,11 @@ static void intel_engine_irq_wakeup(struct work_struct *work) { struct intel_engine_cs *engine = container_of(work, struct intel_engine_cs, irq_work); - const bool noirq = !__irq_enable(engine); + bool noirq; DEFINE_WAIT(wait); +restart: + noirq = !__irq_enable(engine); for (;;) { struct timer_list timer; struct drm_i915_gem_request *request; @@ -142,9 +144,14 @@ static void intel_engine_irq_wakeup(struct work_struct *work) destroy_timer_on_stack(&timer); } } - finish_wait(&engine->irq_queue, &wait); if (!noirq) engine->irq_put(engine); + + prepare_to_wait(&engine->irq_queue, &wait, TASK_UNINTERRUPTIBLE); + if (schedule_timeout(msecs_to_jiffies_timeout(20)) > 0) + goto restart; + + finish_wait(&engine->irq_queue, &wait); } void intel_engine_init_wakeups(struct intel_engine_cs *engine) @@ -163,8 +170,10 @@ void intel_engine_add_wakeup(struct drm_i915_gem_request *request) struct rb_node **p, *parent; bool first; - if (RB_EMPTY_ROOT(&engine->irq_requests)) + if (RB_EMPTY_ROOT(&engine->irq_requests)) { schedule_work(&engine->irq_work); + wake_up_all(&engine->irq_queue); + } init_waitqueue_head(&request->wait); -- Chris Wilson, Intel Open Source Technology Centre _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx