diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2018-11-02 12:12:12 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2018-11-19 12:16:44 -0500 |
commit | fb6f0b64e455b207a636346588e65bf9598d30eb (patch) | |
tree | 624fc138521ce6070fe0c23a71e589fc32b50aa9 | |
parent | 31579ba22c0c5b7645087823904a5780d2385d4a (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.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gpu_error.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gpu_error.h | 8 |
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 | |||
1933 | void 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 | ||
344 | struct i915_gpu_state *i915_first_error_state(struct drm_i915_private *i915); | 344 | struct i915_gpu_state *i915_first_error_state(struct drm_i915_private *i915); |
345 | void i915_reset_error_state(struct drm_i915_private *i915); | 345 | void i915_reset_error_state(struct drm_i915_private *i915); |
346 | void 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, | |||
355 | static inline struct i915_gpu_state * | 356 | static inline struct i915_gpu_state * |
356 | i915_first_error_state(struct drm_i915_private *i915) | 357 | i915_first_error_state(struct drm_i915_private *i915) |
357 | { | 358 | { |
358 | return NULL; | 359 | return ERR_PTR(-ENODEV); |
359 | } | 360 | } |
360 | 361 | ||
361 | static inline void i915_reset_error_state(struct drm_i915_private *i915) | 362 | static inline void i915_reset_error_state(struct drm_i915_private *i915) |
362 | { | 363 | { |
363 | } | 364 | } |
364 | 365 | ||
366 | static 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_ */ |