Skip to content

Commit

Permalink
drm/i915: extract gt interrupt handler
Browse files Browse the repository at this point in the history
vlv, ivb and snb all share the gen6+ gt irq handling. 3 copies of the
same stuff is a bit much, so extract it into a little helper.

Now ilk has a different gt irq handling than snb, but shares the same
irq handler (due to the similar display block). So also extract the
ilk gt irq handling to clearly separate these two things.

Nice side effect of this is that we can complete Ben Widawsky's gen6+
irq bit #define cleanup and call the render irq also with the GEN6
alias. Beforehand that code was shared with ilk, and neither option
really made much sense.

As a bonus this enables the error interrupt handling lifted from the
vlv code on snb and ivb, too.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Antagonized-by: Ben Widawsky <ben@bwidawsk.net>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Daniel Vetter committed Apr 9, 2012
1 parent 901781b commit e7b4c6b
Showing 1 changed file with 37 additions and 29 deletions.
66 changes: 37 additions & 29 deletions drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,27 @@ static void gen6_pm_rps_work(struct work_struct *work)
mutex_unlock(&dev_priv->dev->struct_mutex);
}

static void snb_gt_irq_handler(struct drm_device *dev,
struct drm_i915_private *dev_priv,
u32 gt_iir)
{

if (gt_iir & (GEN6_RENDER_USER_INTERRUPT |
GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT))
notify_ring(dev, &dev_priv->ring[RCS]);
if (gt_iir & GEN6_BSD_USER_INTERRUPT)
notify_ring(dev, &dev_priv->ring[VCS]);
if (gt_iir & GEN6_BLITTER_USER_INTERRUPT)
notify_ring(dev, &dev_priv->ring[BCS]);

if (gt_iir & (GT_GEN6_BLT_CS_ERROR_INTERRUPT |
GT_GEN6_BSD_CS_ERROR_INTERRUPT |
GT_RENDER_CS_ERROR_INTERRUPT)) {
DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir);
i915_handle_error(dev, false);
}
}

static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
Expand Down Expand Up @@ -458,19 +479,7 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)

ret = IRQ_HANDLED;

if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY))
notify_ring(dev, &dev_priv->ring[RCS]);
if (gt_iir & GT_GEN6_BSD_USER_INTERRUPT)
notify_ring(dev, &dev_priv->ring[VCS]);
if (gt_iir & GT_GEN6_BLT_USER_INTERRUPT)
notify_ring(dev, &dev_priv->ring[BCS]);

if (gt_iir & (GT_GEN6_BLT_CS_ERROR_INTERRUPT |
GT_GEN6_BSD_CS_ERROR_INTERRUPT |
GT_RENDER_CS_ERROR_INTERRUPT)) {
DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir);
i915_handle_error(dev, false);
}
snb_gt_irq_handler(dev, dev_priv, gt_iir);

spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
for_each_pipe(pipe) {
Expand Down Expand Up @@ -618,12 +627,7 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
READ_BREADCRUMB(dev_priv);
}

if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY))
notify_ring(dev, &dev_priv->ring[RCS]);
if (gt_iir & GEN6_BSD_USER_INTERRUPT)
notify_ring(dev, &dev_priv->ring[VCS]);
if (gt_iir & GEN6_BLITTER_USER_INTERRUPT)
notify_ring(dev, &dev_priv->ring[BCS]);
snb_gt_irq_handler(dev, dev_priv, gt_iir);

if (de_iir & DE_GSE_IVB)
intel_opregion_gse_intr(dev);
Expand Down Expand Up @@ -675,6 +679,16 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
return ret;
}

static void ilk_gt_irq_handler(struct drm_device *dev,
struct drm_i915_private *dev_priv,
u32 gt_iir)
{
if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY))
notify_ring(dev, &dev_priv->ring[RCS]);
if (gt_iir & GT_BSD_USER_INTERRUPT)
notify_ring(dev, &dev_priv->ring[VCS]);
}

static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
Expand All @@ -683,13 +697,9 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir;
u32 hotplug_mask;
struct drm_i915_master_private *master_priv;
u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT;

atomic_inc(&dev_priv->irq_received);

if (IS_GEN6(dev))
bsd_usr_interrupt = GEN6_BSD_USER_INTERRUPT;

/* disable master interrupt before clearing iir */
de_ier = I915_READ(DEIER);
I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
Expand Down Expand Up @@ -718,12 +728,10 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
READ_BREADCRUMB(dev_priv);
}

if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY))
notify_ring(dev, &dev_priv->ring[RCS]);
if (gt_iir & bsd_usr_interrupt)
notify_ring(dev, &dev_priv->ring[VCS]);
if (gt_iir & GEN6_BLITTER_USER_INTERRUPT)
notify_ring(dev, &dev_priv->ring[BCS]);
if (IS_GEN5(dev))
ilk_gt_irq_handler(dev, dev_priv, gt_iir);
else
snb_gt_irq_handler(dev, dev_priv, gt_iir);

if (de_iir & DE_GSE)
intel_opregion_gse_intr(dev);
Expand Down

0 comments on commit e7b4c6b

Please sign in to comment.