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

Chris Wilson chris at chris-wilson.co.uk
Mon Nov 2 07:28:22 PST 2015


On Mon, Nov 02, 2015 at 02:57:47PM +0000, Gong, Zhipeng wrote:
> > -----Original Message-----
> > From: Chris Wilson [mailto:chris at chris-wilson.co.uk]
> > Sent: Monday, November 02, 2015 10:16 PM
> > To: Gong, Zhipeng
> > Cc: intel-gfx at lists.freedesktop.org; Rogozhkin, Dmitry V
> > Subject: Re: [PATCH] RFC drm/i915: Slaughter the thundering
> > i915_wait_request herd
> > 
> > On Mon, Nov 02, 2015 at 02:00:47PM +0000, Gong, Zhipeng wrote:
> > > Attach the perf data for BDW async1 and async5 with or without patch.
> > 
> > Hmm, I can see it is the i915_spin_request() consuming the time, but I was
> > hoping to get the callgraph so I could see where the call to i915_wait_request
> > was originating from. Could you regenerate the perf report with -g (or maybe
> > you need a slightly newer perf)?
> > -Chris
> > 
> Chris, I dump the it to txt, but it is hard to read since the call chain is too long.
> If you need the data in other format, please let me know.

Just get a wider monitor :)

Ok, that does confirm that it is the frequent inter-ring sync keeping
the waitqueue short.

If you try,

diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 21017daecb90..008b43be791f 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -70,6 +70,8 @@ static void intel_engine_irq_wakeup(struct work_struct *work)
                container_of(work, struct intel_engine_cs, irq_work);
        const bool noirq = !__irq_enable(engine);
        DEFINE_WAIT(wait);
+#define KEEPALIVE 10
+       int keepalive = KEEPALIVE;
 
        for (;;) {
                struct timer_list timer;
@@ -115,8 +117,11 @@ static void intel_engine_irq_wakeup(struct work_struct *work)
                }
                engine->irq_first = request;
                spin_unlock(&engine->irq_lock);
-               if (request == NULL)
-                       break;
+               if (request == NULL) {
+                       if (--keepalive == 0)
+                               break;
+               } else
+                       keepalive = KEEPALIVE;
 
                /* Make sure the hangcheck timer is armed in case the GPU
                 * hangs and the request never completes.
@@ -124,7 +129,7 @@ static void intel_engine_irq_wakeup(struct work_struct *work)
                i915_queue_hangcheck(engine->i915);
 
                timer.function = NULL;
-               if (noirq || missed_irq(engine)) {
+               if (request == NULL || noirq || missed_irq(engine)) {
                        setup_timer_on_stack(&timer,
                                             (void (*)(unsigned long))wake_up_process,
                                             (unsigned long)current);
@@ -165,6 +170,8 @@ void intel_engine_add_wakeup(struct drm_i915_gem_request *request)
 
                if (RB_EMPTY_ROOT(&engine->irq_requests))
                        schedule_work(&engine->irq_work);
+               else
+                       wake_up_all(&engine->irq_queue);
 
                init_waitqueue_head(&request->wait);


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).
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre


More information about the Intel-gfx mailing list