[Intel-gfx] [PATCH 12/31] drm/i915: Reduce spinlock hold time during notify_ring() interrupt

Chris Wilson chris at chris-wilson.co.uk
Wed Jun 27 13:14:13 UTC 2018


Quoting Mika Kuoppala (2018-06-27 14:08:34)
> Chris Wilson <chris at chris-wilson.co.uk> writes:
> 
> > By taking advantage of the RCU protection of the task struct, we can find
> > the appropriate signaler under the spinlock and then release the spinlock
> > before waking the task and signaling the fence.
> >
> > Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> > ---
> >  drivers/gpu/drm/i915/i915_irq.c | 33 ++++++++++++++++++++++-----------
> >  1 file changed, 22 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > index 316d0b08d40f..53dad48f92ce 100644
> > --- a/drivers/gpu/drm/i915/i915_irq.c
> > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > @@ -1145,21 +1145,23 @@ static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv)
> >  
> >  static void notify_ring(struct intel_engine_cs *engine)
> >  {
> > +     const u32 seqno = intel_engine_get_seqno(engine);
> >       struct i915_request *rq = NULL;
> > +     struct task_struct *tsk = NULL;
> >       struct intel_wait *wait;
> >  
> > -     if (!engine->breadcrumbs.irq_armed)
> > +     if (unlikely(!engine->breadcrumbs.irq_armed))
> >               return;
> >
> 
> Ok, so due to unlikeliness, you get the seqno early.
> 
> >       atomic_inc(&engine->irq_count);
> > -     set_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted);
> > +
> > +     rcu_read_lock();
> 
> As I understand from irc discussion, we have our own const
> or stable copy of task struct from now on.
> >  
> >       spin_lock(&engine->breadcrumbs.irq_lock);
> >       wait = engine->breadcrumbs.irq_wait;
> >       if (wait) {
> > -             bool wakeup = engine->irq_seqno_barrier;
> > -
> > -             /* We use a callback from the dma-fence to submit
> > +             /*
> > +              * We use a callback from the dma-fence to submit
> >                * requests after waiting on our own requests. To
> >                * ensure minimum delay in queuing the next request to
> >                * hardware, signal the fence now rather than wait for
> > @@ -1170,19 +1172,23 @@ static void notify_ring(struct intel_engine_cs *engine)
> >                * and to handle coalescing of multiple seqno updates
> >                * and many waiters.
> >                */
> > -             if (i915_seqno_passed(intel_engine_get_seqno(engine),
> > -                                   wait->seqno)) {
> > +             if (i915_seqno_passed(seqno, wait->seqno)) {
> >                       struct i915_request *waiter = wait->request;
> >  
> > -                     wakeup = true;
> >                       if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
> >                                     &waiter->fence.flags) &&
> >                           intel_wait_check_request(wait, waiter))
> >                               rq = i915_request_get(waiter);
> > -             }
> >  
> > -             if (wakeup)
> > -                     wake_up_process(wait->tsk);
> > +                     tsk = wait->tsk;
> > +             } else {
> > +                     if (engine->irq_seqno_barrier &&
> > +                         i915_seqno_passed(seqno, wait->seqno - 1)) {
> > +                             set_bit(ENGINE_IRQ_BREADCRUMB,
> > +                                     &engine->irq_posted);
> > +                             tsk = wait->tsk;
> 
> Hmm, you are optimistic that the latency of wakeup will be on par
> or greater than the next request completion?
> 
> And wait side notices too that we are close and spins,
> instead of going back to sleep?

Don't forget this is the missed breadcrumb mitigation for gen5-gen7, and
only for it. The intent is to keep that away from the paths that do not
need the extra delays.

> > +                     }
> > +             }
> >       } else {
> >               if (engine->breadcrumbs.irq_armed)
> >                       __intel_engine_disarm_breadcrumbs(engine);
> > @@ -1195,6 +1201,11 @@ static void notify_ring(struct intel_engine_cs *engine)
> >               i915_request_put(rq);
> >       }
> >  
> > +     if (tsk && tsk->state & TASK_NORMAL)
> > +             wake_up_process(tsk);
> > +
> 
> Why the TASK_NORMAL check?

*shrug* too long spent watching the signaler on gen6, i.e. I grown
accustomed to expecting the tsk to be running at this point.
-Chris


More information about the Intel-gfx mailing list