Skip to content

Commit

Permalink
drm/i915: Reset logical ring contexts' head and tail during GPU reset
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Thomas Daniel authored and Daniel Vetter committed Feb 23, 2015
1 parent b766879 commit 3e5b6f0
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 4 deletions.
12 changes: 8 additions & 4 deletions drivers/gpu/drm/i915/i915_gem_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,11 +296,15 @@ void i915_gem_context_reset(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
int i;

/* In execlists mode we will unreference the context when the execlist
* queue is cleared and the requests destroyed.
*/
if (i915.enable_execlists)
if (i915.enable_execlists) {
struct intel_context *ctx;

list_for_each_entry(ctx, &dev_priv->context_list, link) {
intel_lr_context_reset(dev, ctx);
}

return;
}

for (i = 0; i < I915_NUM_RINGS; i++) {
struct intel_engine_cs *ring = &dev_priv->ring[i];
Expand Down
35 changes: 35 additions & 0 deletions drivers/gpu/drm/i915/intel_lrc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1991,3 +1991,38 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,
drm_gem_object_unreference(&ctx_obj->base);
return ret;
}

void intel_lr_context_reset(struct drm_device *dev,
struct intel_context *ctx)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *ring;
int i;

for_each_ring(ring, dev_priv, i) {
struct drm_i915_gem_object *ctx_obj =
ctx->engine[ring->id].state;
struct intel_ringbuffer *ringbuf =
ctx->engine[ring->id].ringbuf;
uint32_t *reg_state;
struct page *page;

if (!ctx_obj)
continue;

if (i915_gem_object_get_pages(ctx_obj)) {
WARN(1, "Failed get_pages for context obj\n");
continue;
}
page = i915_gem_object_get_page(ctx_obj, 1);
reg_state = kmap_atomic(page);

reg_state[CTX_RING_HEAD+1] = 0;
reg_state[CTX_RING_TAIL+1] = 0;

kunmap_atomic(reg_state);

ringbuf->head = 0;
ringbuf->tail = 0;
}
}
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/intel_lrc.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,
struct intel_engine_cs *ring);
void intel_lr_context_unpin(struct intel_engine_cs *ring,
struct intel_context *ctx);
void intel_lr_context_reset(struct drm_device *dev,
struct intel_context *ctx);

/* Execlists */
int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists);
Expand Down

0 comments on commit 3e5b6f0

Please sign in to comment.