drm/i915: clear error registers after error capture
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>
Thu, 30 Aug 2018 13:24:24 +0000 (14:24 +0100)
committerLionel Landwerlin <lionel.g.landwerlin@intel.com>
Thu, 30 Aug 2018 16:00:41 +0000 (17:00 +0100)
We need to clear the register in order to get correct value after the
next potential hang.

v2: Centralize error register clearing in i915_irq.c (Chris)

v3: Don't read gen8 register on < gen6 (Chris)

v4: Don't swap gen8+ & gen6+ code... (Chris)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20180830132424.21940-1-lionel.g.landwerlin@intel.com
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_irq.c

index 611b71462d3a766b6d21972371ec261023dd290c..14e5628873079f9d5761cef67330c06d4889fa81 100644 (file)
@@ -2807,6 +2807,8 @@ extern void intel_irq_fini(struct drm_i915_private *dev_priv);
 int intel_irq_install(struct drm_i915_private *dev_priv);
 void intel_irq_uninstall(struct drm_i915_private *dev_priv);
 
+void i915_clear_error_registers(struct drm_i915_private *dev_priv);
+
 static inline bool intel_gvt_active(struct drm_i915_private *dev_priv)
 {
        return dev_priv->gvt;
index 4137af4bd8f51f3c5cb128835d06e877c193691f..d9d44639ba266f1af6b8adbc6a535e1b74a9de80 100644 (file)
@@ -2337,7 +2337,7 @@ static bool needs_idle_maps(struct drm_i915_private *dev_priv)
        return IS_GEN5(dev_priv) && IS_MOBILE(dev_priv) && intel_vtd_active();
 }
 
-static void gen6_check_and_clear_faults(struct drm_i915_private *dev_priv)
+static void gen6_check_faults(struct drm_i915_private *dev_priv)
 {
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
@@ -2355,15 +2355,11 @@ static void gen6_check_and_clear_faults(struct drm_i915_private *dev_priv)
                                         fault & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT",
                                         RING_FAULT_SRCID(fault),
                                         RING_FAULT_FAULT_TYPE(fault));
-                       I915_WRITE(RING_FAULT_REG(engine),
-                                  fault & ~RING_FAULT_VALID);
                }
        }
-
-       POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS]));
 }
 
-static void gen8_check_and_clear_faults(struct drm_i915_private *dev_priv)
+static void gen8_check_faults(struct drm_i915_private *dev_priv)
 {
        u32 fault = I915_READ(GEN8_RING_FAULT_REG);
 
@@ -2388,22 +2384,20 @@ static void gen8_check_and_clear_faults(struct drm_i915_private *dev_priv)
                                 GEN8_RING_FAULT_ENGINE_ID(fault),
                                 RING_FAULT_SRCID(fault),
                                 RING_FAULT_FAULT_TYPE(fault));
-               I915_WRITE(GEN8_RING_FAULT_REG,
-                          fault & ~RING_FAULT_VALID);
        }
-
-       POSTING_READ(GEN8_RING_FAULT_REG);
 }
 
 void i915_check_and_clear_faults(struct drm_i915_private *dev_priv)
 {
        /* From GEN8 onwards we only have one 'All Engine Fault Register' */
        if (INTEL_GEN(dev_priv) >= 8)
-               gen8_check_and_clear_faults(dev_priv);
+               gen8_check_faults(dev_priv);
        else if (INTEL_GEN(dev_priv) >= 6)
-               gen6_check_and_clear_faults(dev_priv);
+               gen6_check_faults(dev_priv);
        else
                return;
+
+       i915_clear_error_registers(dev_priv);
 }
 
 void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv)
index 8084e35b25c543afe973ceb9019f1f69431422ce..e31093ce871c35b80fc0c8d76ea13bdf4940ae00 100644 (file)
@@ -3215,7 +3215,7 @@ static void i915_reset_device(struct drm_i915_private *dev_priv,
                kobject_uevent_env(kobj, KOBJ_CHANGE, reset_done_event);
 }
 
-static void i915_clear_error_registers(struct drm_i915_private *dev_priv)
+void i915_clear_error_registers(struct drm_i915_private *dev_priv)
 {
        u32 eir;
 
@@ -3238,6 +3238,22 @@ static void i915_clear_error_registers(struct drm_i915_private *dev_priv)
                I915_WRITE(EMR, I915_READ(EMR) | eir);
                I915_WRITE(IIR, I915_MASTER_ERROR_INTERRUPT);
        }
+
+       if (INTEL_GEN(dev_priv) >= 8) {
+               I915_WRITE(GEN8_RING_FAULT_REG,
+                          I915_READ(GEN8_RING_FAULT_REG) & ~RING_FAULT_VALID);
+               POSTING_READ(GEN8_RING_FAULT_REG);
+       } else if (INTEL_GEN(dev_priv) >= 6) {
+               struct intel_engine_cs *engine;
+               enum intel_engine_id id;
+
+               for_each_engine(engine, dev_priv, id) {
+                       I915_WRITE(RING_FAULT_REG(engine),
+                                  I915_READ(RING_FAULT_REG(engine)) &
+                                  ~RING_FAULT_VALID);
+               }
+               POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS]));
+       }
 }
 
 /**