forked from Minki/linux
drm/i915: extract gt interrupt handler
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>
This commit is contained in:
parent
901781b997
commit
e7b4c6b122
@ -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;
|
||||
@ -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) {
|
||||
@ -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);
|
||||
@ -675,6 +679,16 @@ done:
|
||||
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;
|
||||
@ -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);
|
||||
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user