From: Oscar Mateo <[email protected]>

Otherwise, we might receive a new interrupt before we have time to
ack the first one, eventually missing it.

The right order should be:

1 - Disable Master Interrupt Control.
2 - Find the category of interrupt that is pending.
3 - Find the source(s) of the interrupt and clear the Interrupt Identity bits 
(IIR)
4 - Process the interrupt(s) that had bits set in the IIRs.
5 - Re-enable Master Interrupt Control.

Spotted by Bob Beckett <[email protected]>.

Signed-off-by: Oscar Mateo <[email protected]>
---
 drivers/gpu/drm/i915/i915_irq.c | 89 ++++++++++++++++++++---------------------
 1 file changed, 43 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 9d381cc..59ff177 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1462,6 +1462,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device 
*dev,
        if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) {
                tmp = I915_READ(GEN8_GT_IIR(0));
                if (tmp) {
+                       I915_WRITE(GEN8_GT_IIR(0), tmp);
                        ret = IRQ_HANDLED;
                        rcs = tmp >> GEN8_RCS_IRQ_SHIFT;
                        bcs = tmp >> GEN8_BCS_IRQ_SHIFT;
@@ -1469,7 +1470,6 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device 
*dev,
                                notify_ring(dev, &dev_priv->ring[RCS]);
                        if (bcs & GT_RENDER_USER_INTERRUPT)
                                notify_ring(dev, &dev_priv->ring[BCS]);
-                       I915_WRITE(GEN8_GT_IIR(0), tmp);
                } else
                        DRM_ERROR("The master control interrupt lied (GT0)!\n");
        }
@@ -1477,6 +1477,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device 
*dev,
        if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) {
                tmp = I915_READ(GEN8_GT_IIR(1));
                if (tmp) {
+                       I915_WRITE(GEN8_GT_IIR(1), tmp);
                        ret = IRQ_HANDLED;
                        vcs = tmp >> GEN8_VCS1_IRQ_SHIFT;
                        if (vcs & GT_RENDER_USER_INTERRUPT)
@@ -1484,7 +1485,6 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device 
*dev,
                        vcs = tmp >> GEN8_VCS2_IRQ_SHIFT;
                        if (vcs & GT_RENDER_USER_INTERRUPT)
                                notify_ring(dev, &dev_priv->ring[VCS2]);
-                       I915_WRITE(GEN8_GT_IIR(1), tmp);
                } else
                        DRM_ERROR("The master control interrupt lied (GT1)!\n");
        }
@@ -1492,10 +1492,10 @@ static irqreturn_t gen8_gt_irq_handler(struct 
drm_device *dev,
        if (master_ctl & GEN8_GT_PM_IRQ) {
                tmp = I915_READ(GEN8_GT_IIR(2));
                if (tmp & dev_priv->pm_rps_events) {
-                       ret = IRQ_HANDLED;
-                       gen8_rps_irq_handler(dev_priv, tmp);
                        I915_WRITE(GEN8_GT_IIR(2),
                                   tmp & dev_priv->pm_rps_events);
+                       ret = IRQ_HANDLED;
+                       gen8_rps_irq_handler(dev_priv, tmp);
                } else
                        DRM_ERROR("The master control interrupt lied (PM)!\n");
        }
@@ -1503,11 +1503,11 @@ static irqreturn_t gen8_gt_irq_handler(struct 
drm_device *dev,
        if (master_ctl & GEN8_GT_VECS_IRQ) {
                tmp = I915_READ(GEN8_GT_IIR(3));
                if (tmp) {
+                       I915_WRITE(GEN8_GT_IIR(3), tmp);
                        ret = IRQ_HANDLED;
                        vcs = tmp >> GEN8_VECS_IRQ_SHIFT;
                        if (vcs & GT_RENDER_USER_INTERRUPT)
                                notify_ring(dev, &dev_priv->ring[VECS]);
-                       I915_WRITE(GEN8_GT_IIR(3), tmp);
                } else
                        DRM_ERROR("The master control interrupt lied (GT3)!\n");
        }
@@ -2232,32 +2232,30 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
 
        if (master_ctl & GEN8_DE_MISC_IRQ) {
                tmp = I915_READ(GEN8_DE_MISC_IIR);
-               if (tmp & GEN8_DE_MISC_GSE)
-                       intel_opregion_asle_intr(dev);
-               else if (tmp)
-                       DRM_ERROR("Unexpected DE Misc interrupt\n");
-               else
-                       DRM_ERROR("The master control interrupt lied (DE 
MISC)!\n");
-
                if (tmp) {
                        I915_WRITE(GEN8_DE_MISC_IIR, tmp);
                        ret = IRQ_HANDLED;
+                       if (tmp & GEN8_DE_MISC_GSE)
+                               intel_opregion_asle_intr(dev);
+                       else
+                               DRM_ERROR("Unexpected DE Misc interrupt\n");
                }
+               else
+                       DRM_ERROR("The master control interrupt lied (DE 
MISC)!\n");
        }
 
        if (master_ctl & GEN8_DE_PORT_IRQ) {
                tmp = I915_READ(GEN8_DE_PORT_IIR);
-               if (tmp & GEN8_AUX_CHANNEL_A)
-                       dp_aux_irq_handler(dev);
-               else if (tmp)
-                       DRM_ERROR("Unexpected DE Port interrupt\n");
-               else
-                       DRM_ERROR("The master control interrupt lied (DE 
PORT)!\n");
-
                if (tmp) {
                        I915_WRITE(GEN8_DE_PORT_IIR, tmp);
                        ret = IRQ_HANDLED;
+                       if (tmp & GEN8_AUX_CHANNEL_A)
+                               dp_aux_irq_handler(dev);
+                       else
+                               DRM_ERROR("Unexpected DE Port interrupt\n");
                }
+               else
+                       DRM_ERROR("The master control interrupt lied (DE 
PORT)!\n");
        }
 
        for_each_pipe(pipe) {
@@ -2267,33 +2265,32 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
                        continue;
 
                pipe_iir = I915_READ(GEN8_DE_PIPE_IIR(pipe));
-               if (pipe_iir & GEN8_PIPE_VBLANK)
-                       intel_pipe_handle_vblank(dev, pipe);
-
-               if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) {
-                       intel_prepare_page_flip(dev, pipe);
-                       intel_finish_page_flip_plane(dev, pipe);
-               }
+               if (pipe_iir) {
+                       ret = IRQ_HANDLED;
+                       I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir);
+                       if (pipe_iir & GEN8_PIPE_VBLANK)
+                               intel_pipe_handle_vblank(dev, pipe);
 
-               if (pipe_iir & GEN8_PIPE_CDCLK_CRC_DONE)
-                       hsw_pipe_crc_irq_handler(dev, pipe);
+                       if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) {
+                               intel_prepare_page_flip(dev, pipe);
+                               intel_finish_page_flip_plane(dev, pipe);
+                       }
 
-               if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN) {
-                       if (intel_set_cpu_fifo_underrun_reporting(dev, pipe,
-                                                                 false))
-                               DRM_ERROR("Pipe %c FIFO underrun\n",
-                                         pipe_name(pipe));
-               }
+                       if (pipe_iir & GEN8_PIPE_CDCLK_CRC_DONE)
+                               hsw_pipe_crc_irq_handler(dev, pipe);
 
-               if (pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS) {
-                       DRM_ERROR("Fault errors on pipe %c\n: 0x%08x",
-                                 pipe_name(pipe),
-                                 pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS);
-               }
+                       if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN) {
+                               if (intel_set_cpu_fifo_underrun_reporting(dev, 
pipe,
+                                                                         
false))
+                                       DRM_ERROR("Pipe %c FIFO underrun\n",
+                                                 pipe_name(pipe));
+                       }
 
-               if (pipe_iir) {
-                       ret = IRQ_HANDLED;
-                       I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir);
+                       if (pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS) {
+                               DRM_ERROR("Fault errors on pipe %c\n: 0x%08x",
+                                         pipe_name(pipe),
+                                         pipe_iir & 
GEN8_DE_PIPE_IRQ_FAULT_ERRORS);
+                       }
                } else
                        DRM_ERROR("The master control interrupt lied (DE 
PIPE)!\n");
        }
@@ -2305,13 +2302,13 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
                 * on older pch-split platforms. But this needs testing.
                 */
                u32 pch_iir = I915_READ(SDEIIR);
-
-               cpt_irq_handler(dev, pch_iir);
-
                if (pch_iir) {
                        I915_WRITE(SDEIIR, pch_iir);
                        ret = IRQ_HANDLED;
-               }
+                       cpt_irq_handler(dev, pch_iir);
+               } else
+                       DRM_ERROR("The master control interrupt lied (SDE)!\n");
+
        }
 
        I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
-- 
1.9.0

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to