aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-05-09 16:45:44 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-05-10 05:55:23 -0400
commit0e43406bcc1868a316eea6012a0a09d992c53521 (patch)
tree564d42d86ff0a86c1e01717975e1c58fc6c2df69 /drivers
parent9adab8b5a7fde248504f484e197589f3e3c922e2 (diff)
drm/i915: Simplify interrupt processing for IvyBridge
We can take advantage that the PCH_IIR is a subordinate register to reduce one of the required IIR reads, and that we only need to clear interrupts handled to reduce the writes. And by simply tidying the code we can reduce the line count and hopefully make it more readable. v2: Split out the bugfix from the refactoring. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c87
1 files changed, 38 insertions, 49 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 14943ba4d731..324431e42fdf 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -577,72 +577,61 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
577{ 577{
578 struct drm_device *dev = (struct drm_device *) arg; 578 struct drm_device *dev = (struct drm_device *) arg;
579 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 579 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
580 int ret = IRQ_NONE; 580 u32 de_iir, gt_iir, de_ier, pm_iir;
581 u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir; 581 irqreturn_t ret = IRQ_NONE;
582 int i;
582 583
583 atomic_inc(&dev_priv->irq_received); 584 atomic_inc(&dev_priv->irq_received);
584 585
585 /* disable master interrupt before clearing iir */ 586 /* disable master interrupt before clearing iir */
586 de_ier = I915_READ(DEIER); 587 de_ier = I915_READ(DEIER);
587 I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); 588 I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
588 POSTING_READ(DEIER);
589 589
590 de_iir = I915_READ(DEIIR);
591 gt_iir = I915_READ(GTIIR); 590 gt_iir = I915_READ(GTIIR);
592 pch_iir = I915_READ(SDEIIR); 591 if (gt_iir) {
593 pm_iir = I915_READ(GEN6_PMIIR); 592 snb_gt_irq_handler(dev, dev_priv, gt_iir);
594 593 I915_WRITE(GTIIR, gt_iir);
595 if (de_iir == 0 && gt_iir == 0 && pch_iir == 0 && pm_iir == 0) 594 ret = IRQ_HANDLED;
596 goto done;
597
598 ret = IRQ_HANDLED;
599
600 snb_gt_irq_handler(dev, dev_priv, gt_iir);
601
602 if (de_iir & DE_GSE_IVB)
603 intel_opregion_gse_intr(dev);
604
605 if (de_iir & DE_PLANEA_FLIP_DONE_IVB) {
606 intel_prepare_page_flip(dev, 0);
607 intel_finish_page_flip_plane(dev, 0);
608 }
609
610 if (de_iir & DE_PLANEB_FLIP_DONE_IVB) {
611 intel_prepare_page_flip(dev, 1);
612 intel_finish_page_flip_plane(dev, 1);
613 } 595 }
614 596
615 if (de_iir & DE_PLANEC_FLIP_DONE_IVB) { 597 de_iir = I915_READ(DEIIR);
616 intel_prepare_page_flip(dev, 2); 598 if (de_iir) {
617 intel_finish_page_flip_plane(dev, 2); 599 if (de_iir & DE_GSE_IVB)
618 } 600 intel_opregion_gse_intr(dev);
601
602 for (i = 0; i < 3; i++) {
603 if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) {
604 intel_prepare_page_flip(dev, i);
605 intel_finish_page_flip_plane(dev, i);
606 }
607 if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i)))
608 drm_handle_vblank(dev, i);
609 }
619 610
620 if (de_iir & DE_PIPEA_VBLANK_IVB) 611 /* check event from PCH */
621 drm_handle_vblank(dev, 0); 612 if (de_iir & DE_PCH_EVENT_IVB) {
613 u32 pch_iir = I915_READ(SDEIIR);
622 614
623 if (de_iir & DE_PIPEB_VBLANK_IVB) 615 if (pch_iir & SDE_HOTPLUG_MASK_CPT)
624 drm_handle_vblank(dev, 1); 616 queue_work(dev_priv->wq, &dev_priv->hotplug_work);
617 pch_irq_handler(dev, pch_iir);
625 618
626 if (de_iir & DE_PIPEC_VBLANK_IVB) 619 /* clear PCH hotplug event before clear CPU irq */
627 drm_handle_vblank(dev, 2); 620 I915_WRITE(SDEIIR, pch_iir);
621 }
628 622
629 /* check event from PCH */ 623 I915_WRITE(DEIIR, de_iir);
630 if (de_iir & DE_PCH_EVENT_IVB) { 624 ret = IRQ_HANDLED;
631 if (pch_iir & SDE_HOTPLUG_MASK_CPT)
632 queue_work(dev_priv->wq, &dev_priv->hotplug_work);
633 pch_irq_handler(dev, pch_iir);
634 } 625 }
635 626
636 if (pm_iir & GEN6_PM_DEFERRED_EVENTS) 627 pm_iir = I915_READ(GEN6_PMIIR);
637 gen6_queue_rps_work(dev_priv, pm_iir); 628 if (pm_iir) {
638 629 if (pm_iir & GEN6_PM_DEFERRED_EVENTS)
639 /* should clear PCH hotplug event before clear CPU irq */ 630 gen6_queue_rps_work(dev_priv, pm_iir);
640 I915_WRITE(SDEIIR, pch_iir); 631 I915_WRITE(GEN6_PMIIR, pm_iir);
641 I915_WRITE(GTIIR, gt_iir); 632 ret = IRQ_HANDLED;
642 I915_WRITE(DEIIR, de_iir); 633 }
643 I915_WRITE(GEN6_PMIIR, pm_iir);
644 634
645done:
646 I915_WRITE(DEIER, de_ier); 635 I915_WRITE(DEIER, de_ier);
647 POSTING_READ(DEIER); 636 POSTING_READ(DEIER);
648 637