On Thu, 08 Dec 2011 18:35:24 -0800 Eric Anholt <eric at 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+ */ -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: not available URL: <http://lists.freedesktop.org/archives/intel-gfx/attachments/20111214/6705c82b/attachment.pgp>