aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2018-11-02 12:12:12 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2018-11-19 12:16:44 -0500
commitfb6f0b64e455b207a636346588e65bf9598d30eb (patch)
tree624fc138521ce6070fe0c23a71e589fc32b50aa9
parent31579ba22c0c5b7645087823904a5780d2385d4a (diff)
drm/i915: Prevent machine hang from Broxton's vtd w/a and error capture
Since capturing the error state requires fiddling around with the GGTT to read arbitrary buffers and is itself run under stop_machine(), it deadlocks the machine (effectively a hard hang) when run in conjunction with Broxton's VTd workaround to serialize GGTT access. v2: Store the ERR_PTR in first_error so that the error can be reported to the user via sysfs. v3: Mention the quirk in dmesg (using info as per usual) Fixes: 0ef34ad6222a ("drm/i915: Serialize GTT/Aperture accesses on BXT") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Jon Bloomfield <jon.bloomfield@intel.com> Cc: John Harrison <john.C.Harrison@intel.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20181102161232.17742-5-chris@chris-wilson.co.uk
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c5
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c15
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.h8
3 files changed, 26 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index a98c29147d5e..add1fe7aeb93 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3360,6 +3360,11 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
3360 ggtt->vm.insert_page = bxt_vtd_ggtt_insert_page__BKL; 3360 ggtt->vm.insert_page = bxt_vtd_ggtt_insert_page__BKL;
3361 if (ggtt->vm.clear_range != nop_clear_range) 3361 if (ggtt->vm.clear_range != nop_clear_range)
3362 ggtt->vm.clear_range = bxt_vtd_ggtt_clear_range__BKL; 3362 ggtt->vm.clear_range = bxt_vtd_ggtt_clear_range__BKL;
3363
3364 /* Prevent recursively calling stop_machine() and deadlocks. */
3365 dev_info(dev_priv->drm.dev,
3366 "Disabling error capture for VT-d workaround\n");
3367 i915_disable_error_state(dev_priv, -ENODEV);
3363 } 3368 }
3364 3369
3365 ggtt->invalidate = gen6_ggtt_invalidate; 3370 ggtt->invalidate = gen6_ggtt_invalidate;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index c8d8f79688a8..21b5c8765015 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -648,6 +648,9 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
648 return 0; 648 return 0;
649 } 649 }
650 650
651 if (IS_ERR(error))
652 return PTR_ERR(error);
653
651 if (*error->error_msg) 654 if (*error->error_msg)
652 err_printf(m, "%s\n", error->error_msg); 655 err_printf(m, "%s\n", error->error_msg);
653 err_printf(m, "Kernel: " UTS_RELEASE "\n"); 656 err_printf(m, "Kernel: " UTS_RELEASE "\n");
@@ -1867,6 +1870,7 @@ void i915_capture_error_state(struct drm_i915_private *i915,
1867 error = i915_capture_gpu_state(i915); 1870 error = i915_capture_gpu_state(i915);
1868 if (!error) { 1871 if (!error) {
1869 DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); 1872 DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
1873 i915_disable_error_state(i915, -ENOMEM);
1870 return; 1874 return;
1871 } 1875 }
1872 1876
@@ -1922,5 +1926,14 @@ void i915_reset_error_state(struct drm_i915_private *i915)
1922 i915->gpu_error.first_error = NULL; 1926 i915->gpu_error.first_error = NULL;
1923 spin_unlock_irq(&i915->gpu_error.lock); 1927 spin_unlock_irq(&i915->gpu_error.lock);
1924 1928
1925 i915_gpu_state_put(error); 1929 if (!IS_ERR(error))
1930 i915_gpu_state_put(error);
1931}
1932
1933void i915_disable_error_state(struct drm_i915_private *i915, int err)
1934{
1935 spin_lock_irq(&i915->gpu_error.lock);
1936 if (!i915->gpu_error.first_error)
1937 i915->gpu_error.first_error = ERR_PTR(err);
1938 spin_unlock_irq(&i915->gpu_error.lock);
1926} 1939}
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h
index 8710fb18ed74..3ec89a504de5 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.h
+++ b/drivers/gpu/drm/i915/i915_gpu_error.h
@@ -343,6 +343,7 @@ static inline void i915_gpu_state_put(struct i915_gpu_state *gpu)
343 343
344struct i915_gpu_state *i915_first_error_state(struct drm_i915_private *i915); 344struct i915_gpu_state *i915_first_error_state(struct drm_i915_private *i915);
345void i915_reset_error_state(struct drm_i915_private *i915); 345void i915_reset_error_state(struct drm_i915_private *i915);
346void i915_disable_error_state(struct drm_i915_private *i915, int err);
346 347
347#else 348#else
348 349
@@ -355,13 +356,18 @@ static inline void i915_capture_error_state(struct drm_i915_private *dev_priv,
355static inline struct i915_gpu_state * 356static inline struct i915_gpu_state *
356i915_first_error_state(struct drm_i915_private *i915) 357i915_first_error_state(struct drm_i915_private *i915)
357{ 358{
358 return NULL; 359 return ERR_PTR(-ENODEV);
359} 360}
360 361
361static inline void i915_reset_error_state(struct drm_i915_private *i915) 362static inline void i915_reset_error_state(struct drm_i915_private *i915)
362{ 363{
363} 364}
364 365
366static inline void i915_disable_error_state(struct drm_i915_private *i915,
367 int err)
368{
369}
370
365#endif /* IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) */ 371#endif /* IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) */
366 372
367#endif /* _I915_GPU_ERROR_H_ */ 373#endif /* _I915_GPU_ERROR_H_ */