diff options
author | Thomas Daniel <thomas.daniel@intel.com> | 2015-02-16 11:12:53 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-02-23 18:19:37 -0500 |
commit | 3e5b6f05a23cc1ba92f429e524d6d5b67401132d (patch) | |
tree | 31064b6b05c64bee932458c935ddd5cd3868583f | |
parent | b76687910693b1f6c32a3251a8291d67363bba34 (diff) |
drm/i915: Reset logical ring contexts' head and tail during GPU reset
Work was getting left behind in LRC contexts during reset. This causes a hang
if the GPU is reset when HEAD==TAIL because the context's ringbuffer head and
tail don't get reset and retiring a request doesn't alter them, so the ring
still appears full.
Added a function intel_lr_context_reset() to reset head and tail on a LRC and
its ringbuffer.
Call intel_lr_context_reset() for each context in i915_gem_context_reset() when
in execlists mode.
Testcase: igt/pm_rps --run-subtest reset #bdw
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=88096
Signed-off-by: Thomas Daniel <thomas.daniel@intel.com>
Reviewed-by: Dave Gordon <david.s.gordon@intel.com>
[danvet: Flatten control flow in the lrc reset code a notch.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_context.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lrc.c | 35 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lrc.h | 2 |
3 files changed, 45 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 8603bf48d3ee..70346b0028f9 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
@@ -296,11 +296,15 @@ void i915_gem_context_reset(struct drm_device *dev) | |||
296 | struct drm_i915_private *dev_priv = dev->dev_private; | 296 | struct drm_i915_private *dev_priv = dev->dev_private; |
297 | int i; | 297 | int i; |
298 | 298 | ||
299 | /* In execlists mode we will unreference the context when the execlist | 299 | if (i915.enable_execlists) { |
300 | * queue is cleared and the requests destroyed. | 300 | struct intel_context *ctx; |
301 | */ | 301 | |
302 | if (i915.enable_execlists) | 302 | list_for_each_entry(ctx, &dev_priv->context_list, link) { |
303 | intel_lr_context_reset(dev, ctx); | ||
304 | } | ||
305 | |||
303 | return; | 306 | return; |
307 | } | ||
304 | 308 | ||
305 | for (i = 0; i < I915_NUM_RINGS; i++) { | 309 | for (i = 0; i < I915_NUM_RINGS; i++) { |
306 | struct intel_engine_cs *ring = &dev_priv->ring[i]; | 310 | struct intel_engine_cs *ring = &dev_priv->ring[i]; |
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 98c87f617bf2..0bd0a9cfca8c 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c | |||
@@ -1991,3 +1991,38 @@ error_unpin_ctx: | |||
1991 | drm_gem_object_unreference(&ctx_obj->base); | 1991 | drm_gem_object_unreference(&ctx_obj->base); |
1992 | return ret; | 1992 | return ret; |
1993 | } | 1993 | } |
1994 | |||
1995 | void intel_lr_context_reset(struct drm_device *dev, | ||
1996 | struct intel_context *ctx) | ||
1997 | { | ||
1998 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1999 | struct intel_engine_cs *ring; | ||
2000 | int i; | ||
2001 | |||
2002 | for_each_ring(ring, dev_priv, i) { | ||
2003 | struct drm_i915_gem_object *ctx_obj = | ||
2004 | ctx->engine[ring->id].state; | ||
2005 | struct intel_ringbuffer *ringbuf = | ||
2006 | ctx->engine[ring->id].ringbuf; | ||
2007 | uint32_t *reg_state; | ||
2008 | struct page *page; | ||
2009 | |||
2010 | if (!ctx_obj) | ||
2011 | continue; | ||
2012 | |||
2013 | if (i915_gem_object_get_pages(ctx_obj)) { | ||
2014 | WARN(1, "Failed get_pages for context obj\n"); | ||
2015 | continue; | ||
2016 | } | ||
2017 | page = i915_gem_object_get_page(ctx_obj, 1); | ||
2018 | reg_state = kmap_atomic(page); | ||
2019 | |||
2020 | reg_state[CTX_RING_HEAD+1] = 0; | ||
2021 | reg_state[CTX_RING_TAIL+1] = 0; | ||
2022 | |||
2023 | kunmap_atomic(reg_state); | ||
2024 | |||
2025 | ringbuf->head = 0; | ||
2026 | ringbuf->tail = 0; | ||
2027 | } | ||
2028 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index f635735df8a1..5dd0ecaf6128 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h | |||
@@ -73,6 +73,8 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, | |||
73 | struct intel_engine_cs *ring); | 73 | struct intel_engine_cs *ring); |
74 | void intel_lr_context_unpin(struct intel_engine_cs *ring, | 74 | void intel_lr_context_unpin(struct intel_engine_cs *ring, |
75 | struct intel_context *ctx); | 75 | struct intel_context *ctx); |
76 | void intel_lr_context_reset(struct drm_device *dev, | ||
77 | struct intel_context *ctx); | ||
76 | 78 | ||
77 | /* Execlists */ | 79 | /* Execlists */ |
78 | int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists); | 80 | int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists); |