[Intel-gfx] [PATCH] drm/i915: Reduce number of register access during IVB+ interrupt handling
Chris Wilson
chris at chris-wilson.co.uk
Mon Sep 23 15:06:09 CEST 2013
On Mon, Sep 23, 2013 at 09:57:37AM -0300, Paulo Zanoni wrote:
> 2013/9/23 Chris Wilson <chris at chris-wilson.co.uk>:
> > Register access is particularly obnoxious on Sandybridge and later due to
> > the extra work we must do around every read or write. The effect is
> > magnified on Haswell, as we have per-operation sanity checking
> > magnifying the number of reads and writes.
> >
> > Interrupt handling is supposed to be fast, yet due to the sanity checks
> > around the register accesss it is not as fast as it could be. If we look
> > closer, most of the common register operations are reading values we
> > already know, and redundant flushes. Eliminate these by storing the
> > desired values rather than reading them back during the interrupt
> > routine.
> >
> > Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> > ---
> > drivers/gpu/drm/i915/i915_drv.h | 4 ++--
> > drivers/gpu/drm/i915/i915_irq.c | 22 ++++++++--------------
> > 2 files changed, 10 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index db8e4d0..f182a23 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1259,8 +1259,8 @@ typedef struct drm_i915_private {
> > /* DPIO indirect register protection */
> > struct mutex dpio_lock;
> >
> > - /** Cached value of IMR to avoid reads in updating the bitfield */
> > - u32 irq_mask;
> > + /** Cached value of IMR/IER to avoid reads in updating the bitfield */
> > + u32 irq_mask, irq_enable;
> > u32 gt_irq_mask;
> > u32 pm_irq_mask;
> >
> > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > index d9eebca..76725c6 100644
> > --- a/drivers/gpu/drm/i915/i915_irq.c
> > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > @@ -1428,7 +1428,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
> > {
> > struct drm_device *dev = (struct drm_device *) arg;
> > drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
> > - u32 de_iir, gt_iir, de_ier, sde_ier = 0;
> > + u32 de_iir, gt_iir;
> > irqreturn_t ret = IRQ_NONE;
> >
> > atomic_inc(&dev_priv->irq_received);
> > @@ -1438,20 +1438,15 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
> > intel_uncore_check_errors(dev);
> >
> > /* disable master interrupt before clearing iir */
> > - de_ier = I915_READ(DEIER);
> > - I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
> > - POSTING_READ(DEIER);
> > + I915_WRITE(DEIER, dev_priv->irq_enable & ~DE_MASTER_IRQ_CONTROL);
> >
> > /* Disable south interrupts. We'll only write to SDEIIR once, so further
> > * interrupts will will be stored on its back queue, and then we'll be
> > * able to process them after we restore SDEIER (as soon as we restore
> > * it, we'll get an interrupt if SDEIIR still has something to process
> > * due to its back queue). */
> > - if (!HAS_PCH_NOP(dev)) {
> > - sde_ier = I915_READ(SDEIER);
> > + if (!HAS_PCH_NOP(dev))
> > I915_WRITE(SDEIER, 0);
> > - POSTING_READ(SDEIER);
> > - }
> >
> > gt_iir = I915_READ(GTIIR);
> > if (gt_iir) {
> > @@ -1482,12 +1477,10 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
> > }
> > }
> >
> > - I915_WRITE(DEIER, de_ier);
> > + if (!HAS_PCH_NOP(dev))
> > + I915_WRITE(SDEIER, ~0);
>
> Please don't change the relative order of DEIER and SDEIER. As far as
> I remember, this order is required to prevent the complete stop of
> SDEIER interrupts when we're getting too many of them (e.g.,
> underruns).
The comments refer to the ordering of DEIIR vs SDEIIR, not IER and in
particular the master-irq enable.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
More information about the Intel-gfx
mailing list