On Tue, 2008-11-04 at 02:03 -0800, Keith Packard wrote:
> The pipestat fields affect reporting of all vblank-related interrupts, so we
> have to reset them during the irq_handler, and while enabling vblank
> interrupts.
> 
> This patch adds i915_enable_pipestat and i915_disable_pipestat to abstract
> out the steps needed to change the reported interrupts.

This looks pretty good, and covers a lot of my concerns with interrupt
handling.  See comments, and my additional MSI patch that I required for
stability against wiggling a window over vblank-synced glxgears
(reproducible in <30s before, and I've now spent a couple of minutes
wiggling windows successfully).

> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index b2ba2b6..f7ac581 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -34,28 +34,69 @@
>  #define MAX_NOPID ((u32)~0)
>  
>  /** These are the interrupts used by the driver */
> -#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT |            \
> -                                 I915_ASLE_INTERRUPT |               \
> -                                 I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
> -                                 I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
> +#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \
> +                                I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |  \
> +                                I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
> +
> +#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
> +
> +#define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \
> +                                 I915_INTERRUPT_ENABLE_VAR)
>  
>  void
>  i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
>  {
> -     if ((dev_priv->irq_mask_reg & mask) != 0) {
> -             dev_priv->irq_mask_reg &= ~mask;
> -             I915_WRITE(IMR, dev_priv->irq_mask_reg);
> -             (void) I915_READ(IMR);
> +     mask &= I915_INTERRUPT_ENABLE_VAR;
> +     if ((dev_priv->irq_enable_reg & mask) != mask) {
> +             dev_priv->irq_enable_reg |= mask;
> +             I915_WRITE(IER, dev_priv->irq_enable_reg);
> +             (void) I915_READ(IER);
>       }
>  }

IER versus IMR would be worthwhile to mention in the commit message.

>       spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
> -     /* Enabling vblank events in IMR comes before PIPESTAT write, or
> -      * there's a race where the PIPESTAT vblank bit gets set to 1, so
> -      * the OR of enabled PIPESTAT bits goes to 1, so the PIPExEVENT in
> -      * ISR flashes to 1, but the IIR bit doesn't get set to 1 because
> -      * IMR masks it.  It doesn't ever get set after we clear the masking
> -      * in IMR because the ISR bit is edge, not level-triggered, on the
> -      * OR of PIPESTAT bits.
> -      */
> -     i915_enable_irq(dev_priv, interrupt);
> -     pipestat = I915_READ(pipestat_reg);
> -     if (IS_I965G(dev))
> -             pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE;
> -     else
> -             pipestat |= PIPE_VBLANK_INTERRUPT_ENABLE;
> -     /* Clear any stale interrupt status */
> -     pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
> -                  PIPE_VBLANK_INTERRUPT_STATUS);
> -     I915_WRITE(pipestat_reg, pipestat);
> -     (void) I915_READ(pipestat_reg); /* Posting read */
> +     i915_enable_pipestat(dev_priv, pipe, I915_VBLANK_INTERRUPT_ENABLE);

I'm uncomfortable with the dropping of the START_VBLANK versus VBLANK,
as I'm pretty sure people had figured out that the other bit was bad
news on 965+.

>  int i915_driver_irq_postinstall(struct drm_device *dev)
> @@ -834,23 +805,25 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
>       INIT_WORK(&dev_priv->vblank_work, i915_vblank_work_handler);
>       dev_priv->swaps_pending = 0;
>  
> -     /* Set initial unmasked IRQs to just the selected vblank pipes. */
> -     dev_priv->irq_mask_reg = ~0;
> -
>       ret = drm_vblank_init(dev, num_pipes);
>       if (ret)
>               return ret;
>  
>       dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
> -     dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
> -     dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
>  
>       dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
>  
> -     dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK;
> +     dev_priv->irq_enable_reg = I915_INTERRUPT_ENABLE_FIX;
> +
> +     dev_priv->pipestat[0] = 0;
> +     dev_priv->pipestat[1] = 0;
> +
> +     /* Disable pipe interrupt enables, clear pending pipe status */
> +     I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
> +     I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);

Could we get a PIPESTAT_STATUS_MASK instead of 0x800ffff all over?

-- 
Eric Anholt
[EMAIL PROTECTED]                         [EMAIL PROTECTED]


Attachment: signature.asc
Description: This is a digitally signed message part

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to