@@ -1761,7 +1761,12 @@ void i915_reset(struct drm_i915_private *dev_priv)
pr_notice("drm/i915: Resetting chip after gpu hang\n");
disable_irq(dev_priv->drm.irq);
- i915_gem_reset_prepare(dev_priv);
+ ret = i915_gem_reset_prepare(dev_priv);
+ if (ret) {
+ DRM_ERROR("GPU recovery failed\n");
+ intel_gpu_reset(dev_priv, ALL_ENGINES);
+ goto error;
+ }
ret = intel_gpu_reset(dev_priv, ALL_ENGINES);
if (ret) {
@@ -3328,7 +3328,7 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error)
return READ_ONCE(error->reset_count);
}
-void i915_gem_reset_prepare(struct drm_i915_private *dev_priv);
+int i915_gem_reset_prepare(struct drm_i915_private *dev_priv);
void i915_gem_reset_finish(struct drm_i915_private *dev_priv);
void i915_gem_set_wedged(struct drm_i915_private *dev_priv);
void i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
@@ -2625,16 +2625,28 @@ static bool engine_stalled(struct intel_engine_cs *engine)
return true;
}
-void i915_gem_reset_prepare(struct drm_i915_private *dev_priv)
+int i915_gem_reset_prepare(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
enum intel_engine_id id;
+ int err = 0;
/* Ensure irq handler finishes, and not run again. */
- for_each_engine(engine, dev_priv, id)
+ for_each_engine(engine, dev_priv, id) {
+ struct drm_i915_gem_request *request;
+
tasklet_kill(&engine->irq_tasklet);
+ if (engine_stalled(engine)) {
+ request = i915_gem_find_active_request(engine);
+ if (request && request->fence.error == -EIO)
+ err = -EIO; /* Previous reset failed! */
+ }
+ }
+
i915_gem_revoke_fences(dev_priv);
+
+ return err;
}
static void skip_request(struct drm_i915_gem_request *request)