drm/i915: Always sanity check engine state upon idling
authorChris Wilson <chris@chris-wilson.co.uk>
Sat, 26 Aug 2017 11:09:33 +0000 (12:09 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Tue, 29 Aug 2017 15:56:04 +0000 (16:56 +0100)
When we do a locked idle we know that afterwards all requests have been
completed and the engines have been cleared of tasks. For whatever
reason, this doesn't always happen and we may go into a suspend with
ELSP still full, and this causes an issue upon resume as we get very,
very confused.

If the engines refuse to idle, mark the device as wedged. In the process
we get rid of the maybe unused open-coded version of wait_for_engines
reported by Nick Desaulniers and Matthias Kaehlcke.

v2: Suppress the -EIO before suspend, but keep it for seqno wrap.

References: https://bugs.freedesktop.org/show_bug.cgi?id=101891
References: https://bugs.freedesktop.org/show_bug.cgi?id=102456
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Matthias Kaehlcke <mka@chromium.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20170826110935.10237-1-chris@chris-wilson.co.uk
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
drivers/gpu/drm/i915/i915_gem.c

index 51a8dbbf27bd580ae290dc5b593b254cc329c74a..a1ba989f8da5956304190cf73b04a8ff59c2adda 100644 (file)
@@ -3376,24 +3376,12 @@ static int wait_for_timeline(struct i915_gem_timeline *tl, unsigned int flags)
        return 0;
 }
 
-static int wait_for_engine(struct intel_engine_cs *engine, int timeout_ms)
-{
-       return wait_for(intel_engine_is_idle(engine), timeout_ms);
-}
-
 static int wait_for_engines(struct drm_i915_private *i915)
 {
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
-
-       for_each_engine(engine, i915, id) {
-               if (GEM_WARN_ON(wait_for_engine(engine, 50))) {
-                       i915_gem_set_wedged(i915);
-                       return -EIO;
-               }
-
-               GEM_BUG_ON(intel_engine_get_seqno(engine) !=
-                          intel_engine_last_submit(engine));
+       if (wait_for(intel_engines_are_idle(i915), 50)) {
+               DRM_ERROR("Failed to idle engines, declaring wedged!\n");
+               i915_gem_set_wedged(i915);
+               return -EIO;
        }
 
        return 0;
@@ -4574,7 +4562,7 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv)
        ret = i915_gem_wait_for_idle(dev_priv,
                                     I915_WAIT_INTERRUPTIBLE |
                                     I915_WAIT_LOCKED);
-       if (ret)
+       if (ret && ret != -EIO)
                goto err_unlock;
 
        assert_kernel_context_is_current(dev_priv);
@@ -4618,11 +4606,12 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv)
         * machine in an unusable condition.
         */
        i915_gem_sanitize(dev_priv);
-       goto out_rpm_put;
+
+       intel_runtime_pm_put(dev_priv);
+       return 0;
 
 err_unlock:
        mutex_unlock(&dev->struct_mutex);
-out_rpm_put:
        intel_runtime_pm_put(dev_priv);
        return ret;
 }