[Intel-gfx] [PATCH 1/4] drm/i915: Fix PIPESTATE irq ack on i965/g4x

Chris Wilson chris at chris-wilson.co.uk
Mon Jun 11 20:53:52 UTC 2018


Quoting Ville Syrjala (2018-06-11 21:02:55)
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
> 
> On i965/g4x IIR is edge triggered. So in order for IIR to notice that
> there is still a pending interrupt we have to force and edge in ISR.
> For the ISR/IIR pipe event bits we can do that by temporarily
> clearing all the PIPESTAT enable bits when we ack the status bits.
> This will force the ISR pipe event bit low, and it can then go back
> high when we restore the PIPESTAT enable bits.
> 
> This avoids the following race:
> 1. stat = read(PIPESTAT)
> 2. an enabled PIPESTAT status bit goes high
> 3. write(PIPESTAT, enable|stat);
> 4. write(IIR, PIPE_EVENT)
> 
> The end result is IIR==0 and ISR!=0. This can lead to nasty
> vblank wait/flip_done timeouts if another interrupt source
> doesn't trick us into looking at the PIPESTAT status bits despite
> the IIR PIPE_EVENT bit being low.
> 
> Before i965 IIR was level triggered so this problem can't actually
> happen there. And curiously VLV/CHV went back to the level triggered
> scheme as well. But for simplicity we'll use the same i965/g4x
> compatible code for all platforms.
> 
> Cc: stable at vger.kernel.org
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=106033
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105225
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=106030
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_irq.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 2fd92a886789..364e1c85315e 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -1893,9 +1893,17 @@ static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv,
>  
>                 /*
>                  * Clear the PIPE*STAT regs before the IIR
> +                *
> +                * Toggle the enable bits to make sure we get an
> +                * edge in the ISR pipe event bit if we don't clear
> +                * all the enabled status bits. Otherwise the edge
> +                * triggered IIR on i965/g4x wouldn't notice that
> +                * an interrupt is still pending.
>                  */
> -               if (pipe_stats[pipe])
> -                       I915_WRITE(reg, enable_mask | pipe_stats[pipe]);
> +               if (pipe_stats[pipe]) {
> +                       I915_WRITE(reg, pipe_stats[pipe]);

Ack status, disable all.

> +                       I915_WRITE(reg, enable_mask);

Enable, an asserted bit should trigger a new edge.

It certainly does as you explain, now I just hope the hw feels the same!

Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
-Chris


More information about the Intel-gfx mailing list