[Intel-gfx] [PATCH] RFC drm/i915: Slaughter the thundering i915_wait_request herd

Chris Wilson chris at chris-wilson.co.uk
Mon Nov 2 12:58:30 PST 2015


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


More information about the Intel-gfx mailing list