提交 c7c85101 编写于 作者: Z Zou Nan hai 提交者: Eric Anholt

drm/i915: remove loop in Ironlake interrupt handler

On Ironlake, there is an interrupt master control bit. With the bit
disabled before clearing IIR, we do not need to handle extra interrupt
in a loop. This patch removes the loop in Ironlake interrupt handler.
It fixed irq lost issue on some Ironlake platforms.

Cc: Stable Team <stable@kernel.org>
Signed-off-by: NZou Nan hai <Nanhai.zou@intel.com>
Signed-off-by: NZhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: NEric Anholt <eric@anholt.net>
上级 b9241ea3
...@@ -274,7 +274,6 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) ...@@ -274,7 +274,6 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int ret = IRQ_NONE; int ret = IRQ_NONE;
u32 de_iir, gt_iir, de_ier, pch_iir; u32 de_iir, gt_iir, de_ier, pch_iir;
u32 new_de_iir, new_gt_iir, new_pch_iir;
struct drm_i915_master_private *master_priv; struct drm_i915_master_private *master_priv;
/* disable master interrupt before clearing iir */ /* disable master interrupt before clearing iir */
...@@ -286,51 +285,42 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) ...@@ -286,51 +285,42 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
gt_iir = I915_READ(GTIIR); gt_iir = I915_READ(GTIIR);
pch_iir = I915_READ(SDEIIR); pch_iir = I915_READ(SDEIIR);
for (;;) { if (de_iir == 0 && gt_iir == 0 && pch_iir == 0)
if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) goto done;
break;
ret = IRQ_HANDLED;
/* should clear PCH hotplug event before clear CPU irq */ ret = IRQ_HANDLED;
I915_WRITE(SDEIIR, pch_iir);
new_pch_iir = I915_READ(SDEIIR);
I915_WRITE(DEIIR, de_iir); if (dev->primary->master) {
new_de_iir = I915_READ(DEIIR); master_priv = dev->primary->master->driver_priv;
I915_WRITE(GTIIR, gt_iir); if (master_priv->sarea_priv)
new_gt_iir = I915_READ(GTIIR); master_priv->sarea_priv->last_dispatch =
READ_BREADCRUMB(dev_priv);
if (dev->primary->master) { }
master_priv = dev->primary->master->driver_priv;
if (master_priv->sarea_priv)
master_priv->sarea_priv->last_dispatch =
READ_BREADCRUMB(dev_priv);
}
if (gt_iir & GT_USER_INTERRUPT) {
u32 seqno = i915_get_gem_seqno(dev);
dev_priv->mm.irq_gem_seqno = seqno;
trace_i915_gem_request_complete(dev, seqno);
DRM_WAKEUP(&dev_priv->irq_queue);
dev_priv->hangcheck_count = 0;
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
}
if (de_iir & DE_GSE) if (gt_iir & GT_USER_INTERRUPT) {
ironlake_opregion_gse_intr(dev); u32 seqno = i915_get_gem_seqno(dev);
dev_priv->mm.irq_gem_seqno = seqno;
trace_i915_gem_request_complete(dev, seqno);
DRM_WAKEUP(&dev_priv->irq_queue);
dev_priv->hangcheck_count = 0;
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
}
/* check event from PCH */ if (de_iir & DE_GSE)
if ((de_iir & DE_PCH_EVENT) && ironlake_opregion_gse_intr(dev);
(pch_iir & SDE_HOTPLUG_MASK)) {
queue_work(dev_priv->wq, &dev_priv->hotplug_work);
}
de_iir = new_de_iir; /* check event from PCH */
gt_iir = new_gt_iir; if ((de_iir & DE_PCH_EVENT) &&
pch_iir = new_pch_iir; (pch_iir & SDE_HOTPLUG_MASK)) {
queue_work(dev_priv->wq, &dev_priv->hotplug_work);
} }
/* should clear PCH hotplug event before clear CPU irq */
I915_WRITE(SDEIIR, pch_iir);
I915_WRITE(GTIIR, gt_iir);
I915_WRITE(DEIIR, de_iir);
done:
I915_WRITE(DEIER, de_ier); I915_WRITE(DEIER, de_ier);
(void)I915_READ(DEIER); (void)I915_READ(DEIER);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册