Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 119390
b: refs/heads/master
c: cdfbc41
h: refs/heads/master
v: v3
  • Loading branch information
Eric Anholt authored and Dave Airlie committed Nov 24, 2008
1 parent b1c7170 commit d42ab58
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 48 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7c463586427bbbad726ba561bae4ba5acada2481
refs/heads/master: cdfbc41f6d602fc0105fb2b4e0645cc1aa274c12
108 changes: 61 additions & 47 deletions trunk/drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,69 +168,83 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 iir;
u32 pipea_stats = 0, pipeb_stats = 0;
u32 iir, new_iir;
u32 pipea_stats, pipeb_stats;
int vblank = 0;
unsigned long irqflags;

spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
atomic_inc(&dev_priv->irq_received);

if (dev->pdev->msi_enabled)
I915_WRITE(IMR, ~0);
iir = I915_READ(IIR);

if (iir == 0) {
if (dev->pdev->msi_enabled) {
I915_WRITE(IMR, dev_priv->irq_mask_reg);
(void) I915_READ(IMR);
}
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
if (iir == 0)
return IRQ_NONE;
}

/*
* Clear the PIPE(A|B)STAT regs before the IIR
*/
if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
pipea_stats = I915_READ(PIPEASTAT);
I915_WRITE(PIPEASTAT, pipea_stats);
}

if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
pipeb_stats = I915_READ(PIPEBSTAT);
I915_WRITE(PIPEBSTAT, pipeb_stats);
}
do {
pipea_stats = 0;
pipeb_stats = 0;
/*
* Clear the PIPE(A|B)STAT regs before the IIR
*/
if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
pipea_stats = I915_READ(PIPEASTAT);
I915_WRITE(PIPEASTAT, pipea_stats);
spin_unlock_irqrestore(&dev_priv->user_irq_lock,
irqflags);
}

I915_WRITE(IIR, iir);
if (dev->pdev->msi_enabled)
I915_WRITE(IMR, dev_priv->irq_mask_reg);
(void) I915_READ(IIR); /* Flush posted writes */
if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
pipeb_stats = I915_READ(PIPEBSTAT);
I915_WRITE(PIPEBSTAT, pipeb_stats);
spin_unlock_irqrestore(&dev_priv->user_irq_lock,
irqflags);
}

spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
I915_WRITE(IIR, iir);
new_iir = I915_READ(IIR); /* Flush posted writes */

if (dev_priv->sarea_priv)
dev_priv->sarea_priv->last_dispatch =
READ_BREADCRUMB(dev_priv);
if (dev_priv->sarea_priv)
dev_priv->sarea_priv->last_dispatch =
READ_BREADCRUMB(dev_priv);

if (iir & I915_USER_INTERRUPT) {
dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
DRM_WAKEUP(&dev_priv->irq_queue);
}
if (iir & I915_USER_INTERRUPT) {
dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
DRM_WAKEUP(&dev_priv->irq_queue);
}

if (pipea_stats & I915_VBLANK_INTERRUPT_STATUS) {
vblank++;
drm_handle_vblank(dev, 0);
}
if (pipea_stats & I915_VBLANK_INTERRUPT_STATUS) {
vblank++;
drm_handle_vblank(dev, 0);
}

if (pipeb_stats & I915_VBLANK_INTERRUPT_STATUS) {
vblank++;
drm_handle_vblank(dev, 1);
}
if (pipeb_stats & I915_VBLANK_INTERRUPT_STATUS) {
vblank++;
drm_handle_vblank(dev, 1);
}

if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
(iir & I915_ASLE_INTERRUPT))
opregion_asle_intr(dev);
if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
(iir & I915_ASLE_INTERRUPT))
opregion_asle_intr(dev);

/* With MSI, interrupts are only generated when iir
* transitions from zero to nonzero. If another bit got
* set while we were handling the existing iir bits, then
* we would never get another interrupt.
*
* This is fine on non-MSI as well, as if we hit this path
* we avoid exiting the interrupt handler only to generate
* another one.
*
* Note that for MSI this could cause a stray interrupt report
* if an interrupt landed in the time between writing IIR and
* the posting read. This should be rare enough to never
* trigger the 99% of 100,000 interrupts test for disabling
* stray interrupts.
*/
iir = new_iir;
} while (iir != 0);

return IRQ_HANDLED;
}
Expand Down

0 comments on commit d42ab58

Please sign in to comment.