On Thu, 08 Dec 2011 18:35:24 -0800
Eric Anholt <e...@anholt.net> wrote:
> Since MI_FLUSH_DW exists on gen6, and keithp says we still have
> outstanding issues with missed blit IRQs there, I started trying it
> today.  Two kernel branches posted at
> git://people.freedesktop.org/~anholt/linux/
> 
> flush-dw-notify: This is the initial attempt I did with MI_FLUSH_DW with
> internal notify.  Quickly produced missed blit IRQs.  I thought this was
> because the notify was in parallel with the post-sync op, not synced to
> be after.  So I reverted part of the patch and produced...

Bummer, that one looks like it ought to work.

On current drm-intel-next, this patch seems to be preventing missed
IRQs on IVB at least.  Anyone else wanna give it a try and confirm?
I've only tested with Eric's blit-and-wait.c test so far.

-- 
Jesse Barnes, Intel Open Source Technology Center

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index b40004b..cb821a0 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -482,78 +482,83 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
        I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
        POSTING_READ(DEIER);
 
-       de_iir = I915_READ(DEIIR);
-       gt_iir = I915_READ(GTIIR);
-       pch_iir = I915_READ(SDEIIR);
-       pm_iir = I915_READ(GEN6_PMIIR);
+       /*
+        * Try to mitigate dropped IRQs by handling as many as possible
+        * each time we get a physical interrupt.
+        */
+       while (1) {
+               de_iir = I915_READ(DEIIR);
+               gt_iir = I915_READ(GTIIR);
+               pch_iir = I915_READ(SDEIIR);
+               pm_iir = I915_READ(GEN6_PMIIR);
+
+               if (de_iir == 0 && gt_iir == 0 && pch_iir == 0 && pm_iir == 0) {
+                       I915_WRITE(DEIER, de_ier);
+                       POSTING_READ(DEIER);
+                       return ret;
+               }
 
-       if (de_iir == 0 && gt_iir == 0 && pch_iir == 0 && pm_iir == 0)
-               goto done;
+               ret = IRQ_HANDLED;
 
-       ret = IRQ_HANDLED;
+               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 (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 | 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_BLT_USER_INTERRUPT)
+                       notify_ring(dev, &dev_priv->ring[BCS]);
 
-       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_BLT_USER_INTERRUPT)
-               notify_ring(dev, &dev_priv->ring[BCS]);
+               if (de_iir & DE_GSE_IVB)
+                       intel_opregion_gse_intr(dev);
 
-       if (de_iir & DE_GSE_IVB)
-               intel_opregion_gse_intr(dev);
+               if (de_iir & DE_PLANEA_FLIP_DONE_IVB) {
+                       intel_prepare_page_flip(dev, 0);
+                       intel_finish_page_flip_plane(dev, 0);
+               }
 
-       if (de_iir & DE_PLANEA_FLIP_DONE_IVB) {
-               intel_prepare_page_flip(dev, 0);
-               intel_finish_page_flip_plane(dev, 0);
-       }
+               if (de_iir & DE_PLANEB_FLIP_DONE_IVB) {
+                       intel_prepare_page_flip(dev, 1);
+                       intel_finish_page_flip_plane(dev, 1);
+               }
 
-       if (de_iir & DE_PLANEB_FLIP_DONE_IVB) {
-               intel_prepare_page_flip(dev, 1);
-               intel_finish_page_flip_plane(dev, 1);
-       }
+               if (de_iir & DE_PIPEA_VBLANK_IVB)
+                       drm_handle_vblank(dev, 0);
 
-       if (de_iir & DE_PIPEA_VBLANK_IVB)
-               drm_handle_vblank(dev, 0);
+               if (de_iir & DE_PIPEB_VBLANK_IVB)
+                       drm_handle_vblank(dev, 1);
 
-       if (de_iir & DE_PIPEB_VBLANK_IVB)
-               drm_handle_vblank(dev, 1);
+               /* check event from PCH */
+               if (de_iir & DE_PCH_EVENT_IVB) {
+                       if (pch_iir & SDE_HOTPLUG_MASK_CPT)
+                               queue_work(dev_priv->wq,
+                                          &dev_priv->hotplug_work);
+                       pch_irq_handler(dev);
+               }
 
-       /* check event from PCH */
-       if (de_iir & DE_PCH_EVENT_IVB) {
-               if (pch_iir & SDE_HOTPLUG_MASK_CPT)
-                       queue_work(dev_priv->wq, &dev_priv->hotplug_work);
-               pch_irq_handler(dev);
-       }
+               if (pm_iir & GEN6_PM_DEFERRED_EVENTS) {
+                       unsigned long flags;
+                       spin_lock_irqsave(&dev_priv->rps_lock, flags);
+                       WARN(dev_priv->pm_iir & pm_iir,
+                            "Missed a PM interrupt\n");
+                       dev_priv->pm_iir |= pm_iir;
+                       I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
+                       POSTING_READ(GEN6_PMIMR);
+                       spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
+                       queue_work(dev_priv->wq, &dev_priv->rps_work);
+               }
 
-       if (pm_iir & GEN6_PM_DEFERRED_EVENTS) {
-               unsigned long flags;
-               spin_lock_irqsave(&dev_priv->rps_lock, flags);
-               WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
-               dev_priv->pm_iir |= pm_iir;
-               I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
-               POSTING_READ(GEN6_PMIMR);
-               spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
-               queue_work(dev_priv->wq, &dev_priv->rps_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);
+               I915_WRITE(GEN6_PMIIR, pm_iir);
        }
-
-       /* should clear PCH hotplug event before clear CPU irq */
-       I915_WRITE(SDEIIR, pch_iir);
-       I915_WRITE(GTIIR, gt_iir);
-       I915_WRITE(DEIIR, de_iir);
-       I915_WRITE(GEN6_PMIIR, pm_iir);
-
-done:
-       I915_WRITE(DEIER, de_ier);
-       POSTING_READ(DEIER);
-
-       return ret;
 }
 
 static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c 
b/drivers/gpu/drm/i915/intel_ringbuffer.c
index ca70e2f..a9bdcd6 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1301,9 +1301,11 @@ gen6_bsd_ring_get_irq(struct intel_ring_buffer *ring)
 static void
 gen6_bsd_ring_put_irq(struct intel_ring_buffer *ring)
 {
+#if 0
        return gen6_ring_put_irq(ring,
                                 GT_GEN6_BSD_USER_INTERRUPT,
                                 GEN6_BSD_USER_INTERRUPT);
+#endif
 }
 
 /* ring buffer for Video Codec for Gen6+ */

Attachment: signature.asc
Description: PGP signature

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to