aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c68
1 files changed, 29 insertions, 39 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 7cd8110051b6..89a071a3e6fb 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -274,7 +274,6 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
274 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 274 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
275 int ret = IRQ_NONE; 275 int ret = IRQ_NONE;
276 u32 de_iir, gt_iir, de_ier, pch_iir; 276 u32 de_iir, gt_iir, de_ier, pch_iir;
277 u32 new_de_iir, new_gt_iir, new_pch_iir;
278 struct drm_i915_master_private *master_priv; 277 struct drm_i915_master_private *master_priv;
279 278
280 /* disable master interrupt before clearing iir */ 279 /* disable master interrupt before clearing iir */
@@ -286,51 +285,42 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
286 gt_iir = I915_READ(GTIIR); 285 gt_iir = I915_READ(GTIIR);
287 pch_iir = I915_READ(SDEIIR); 286 pch_iir = I915_READ(SDEIIR);
288 287
289 for (;;) { 288 if (de_iir == 0 && gt_iir == 0 && pch_iir == 0)
290 if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) 289 goto done;
291 break;
292
293 ret = IRQ_HANDLED;
294 290
295 /* should clear PCH hotplug event before clear CPU irq */ 291 ret = IRQ_HANDLED;
296 I915_WRITE(SDEIIR, pch_iir);
297 new_pch_iir = I915_READ(SDEIIR);
298 292
299 I915_WRITE(DEIIR, de_iir); 293 if (dev->primary->master) {
300 new_de_iir = I915_READ(DEIIR); 294 master_priv = dev->primary->master->driver_priv;
301 I915_WRITE(GTIIR, gt_iir); 295 if (master_priv->sarea_priv)
302 new_gt_iir = I915_READ(GTIIR); 296 master_priv->sarea_priv->last_dispatch =
303 297 READ_BREADCRUMB(dev_priv);
304 if (dev->primary->master) { 298 }
305 master_priv = dev->primary->master->driver_priv;
306 if (master_priv->sarea_priv)
307 master_priv->sarea_priv->last_dispatch =
308 READ_BREADCRUMB(dev_priv);
309 }
310
311 if (gt_iir & GT_USER_INTERRUPT) {
312 u32 seqno = i915_get_gem_seqno(dev);
313 dev_priv->mm.irq_gem_seqno = seqno;
314 trace_i915_gem_request_complete(dev, seqno);
315 DRM_WAKEUP(&dev_priv->irq_queue);
316 dev_priv->hangcheck_count = 0;
317 mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
318 }
319 299
320 if (de_iir & DE_GSE) 300 if (gt_iir & GT_USER_INTERRUPT) {
321 ironlake_opregion_gse_intr(dev); 301 u32 seqno = i915_get_gem_seqno(dev);
302 dev_priv->mm.irq_gem_seqno = seqno;
303 trace_i915_gem_request_complete(dev, seqno);
304 DRM_WAKEUP(&dev_priv->irq_queue);
305 dev_priv->hangcheck_count = 0;
306 mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
307 }
322 308
323 /* check event from PCH */ 309 if (de_iir & DE_GSE)
324 if ((de_iir & DE_PCH_EVENT) && 310 ironlake_opregion_gse_intr(dev);
325 (pch_iir & SDE_HOTPLUG_MASK)) {
326 queue_work(dev_priv->wq, &dev_priv->hotplug_work);
327 }
328 311
329 de_iir = new_de_iir; 312 /* check event from PCH */
330 gt_iir = new_gt_iir; 313 if ((de_iir & DE_PCH_EVENT) &&
331 pch_iir = new_pch_iir; 314 (pch_iir & SDE_HOTPLUG_MASK)) {
315 queue_work(dev_priv->wq, &dev_priv->hotplug_work);
332 } 316 }
333 317
318 /* should clear PCH hotplug event before clear CPU irq */
319 I915_WRITE(SDEIIR, pch_iir);
320 I915_WRITE(GTIIR, gt_iir);
321 I915_WRITE(DEIIR, de_iir);
322
323done:
334 I915_WRITE(DEIER, de_ier); 324 I915_WRITE(DEIER, de_ier);
335 (void)I915_READ(DEIER); 325 (void)I915_READ(DEIER);
336 326