[Intel-gfx] [PATCH] drm/i915: Reduce number of register access during IVB+ interrupt handling

Paulo Zanoni przanoni at gmail.com
Mon Sep 23 14:57:37 CEST 2013


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


> +       I915_WRITE(DEIER, dev_priv->irq_enable);
>         POSTING_READ(DEIER);
> -       if (!HAS_PCH_NOP(dev)) {
> -               I915_WRITE(SDEIER, sde_ier);
> -               POSTING_READ(SDEIER);
> -       }
>
>         return ret;
>  }
> @@ -2343,11 +2336,12 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
>         }
>
>         dev_priv->irq_mask = ~display_mask;
> +       dev_priv->irq_enable = display_mask | extra_mask;
>
>         /* should always can generate irq */
>         I915_WRITE(DEIIR, I915_READ(DEIIR));
>         I915_WRITE(DEIMR, dev_priv->irq_mask);
> -       I915_WRITE(DEIER, display_mask | extra_mask);
> +       I915_WRITE(DEIER, dev_priv->irq_enable);
>         POSTING_READ(DEIER);
>
>         gen5_gt_irq_postinstall(dev);
> --
> 1.8.4.rc3
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni



More information about the Intel-gfx mailing list