--- drivers/gpu/drm/i915/i915_drv.c | 4 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 66 +++++++++++++++++++++------------ drivers/gpu/drm/i915/i915_gem_context.c | 16 -------- drivers/gpu/drm/i915/intel_lrc.c | 34 ++++++++++++++++- drivers/gpu/drm/i915/intel_ringbuffer.c | 32 ++++++++++------ drivers/gpu/drm/i915/intel_ringbuffer.h | 2 + 7 files changed, 100 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 869baa6a5196..d250dce0c8fb 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1574,7 +1574,7 @@ static int i915_drm_resume(struct drm_device *dev) mutex_lock(&dev->struct_mutex); if (i915_gem_init_hw(dev)) { DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n"); - atomic_or(I915_WEDGED, &dev_priv->gpu_error.reset_counter); + i915_gem_set_wedged(dev_priv); } mutex_unlock(&dev->struct_mutex); @@ -1798,7 +1798,7 @@ int i915_reset(struct drm_i915_private *dev_priv) return 0; error: - atomic_or(I915_WEDGED, &error->reset_counter); + i915_gem_set_wedged(dev_priv); mutex_unlock(&dev->struct_mutex); return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index aacce6625f84..08c212a5f1a8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3224,6 +3224,7 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error) } void i915_gem_reset(struct drm_device *dev); +void i915_gem_set_wedged(struct drm_i915_private *dev_priv); bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force); int __must_check i915_gem_init(struct drm_device *dev); int __must_check i915_gem_init_hw(struct drm_device *dev); @@ -3343,7 +3344,6 @@ void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj); int __must_check i915_gem_context_init(struct drm_device *dev); void i915_gem_context_lost(struct drm_i915_private *dev_priv); void i915_gem_context_fini(struct drm_device *dev); -void i915_gem_context_reset(struct drm_device *dev); int i915_gem_context_open(struct drm_device *dev, struct drm_file *file); void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); int i915_switch_context(struct drm_i915_gem_request *req); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f56fa8ac30bb..1e5c62476585 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2426,23 +2426,57 @@ i915_gem_find_active_request(struct intel_engine_cs *engine) return NULL; } -static void i915_gem_reset_engine_status(struct intel_engine_cs *engine) +static void i915_gem_reset_engine(struct intel_engine_cs *engine) { struct drm_i915_gem_request *request; + struct i915_gem_context *incomplete_ctx; bool ring_hung; + /* Ensure irq handler finishes or is cancelled. */ + tasklet_kill(&engine->irq_tasklet); + request = i915_gem_find_active_request(engine); - if (request == NULL) + if (!request) return; ring_hung = engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG; - i915_set_reset_status(request->ctx, ring_hung); - list_for_each_entry_continue(request, &engine->request_list, link) + engine->reset_hw(engine, request); + + incomplete_ctx = request->ctx; + if (i915_gem_context_is_default(incomplete_ctx)) + incomplete_ctx = NULL; + list_for_each_entry_continue(request, &engine->request_list, link) { + void *vaddr = request->ring->vaddr; + u32 head; + + if (request->ctx != incomplete_ctx) + continue; + + head = request->head; + if (request->postfix < head) { + memset(vaddr + head, 0, request->ring->size - head); + head = 0; + } + memset(vaddr + head, 0, request->postfix - head); + i915_set_reset_status(request->ctx, false); + } +} + +void i915_gem_reset(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_engine_cs *engine; + + for_each_engine(engine, dev_priv) + i915_gem_reset_engine(engine); + + i915_gem_context_lost(dev_priv); + i915_gem_restore_fences(dev); } -static void i915_gem_reset_engine_cleanup(struct intel_engine_cs *engine) +static void i915_gem_cleanup_engine(struct intel_engine_cs *engine) { struct intel_ring *ring; @@ -2459,9 +2493,6 @@ static void i915_gem_reset_engine_cleanup(struct intel_engine_cs *engine) */ if (i915.enable_execlists) { - /* Ensure irq handler finishes or is cancelled. */ - tasklet_kill(&engine->irq_tasklet); - INIT_LIST_HEAD(&engine->execlist_queue); i915_gem_request_assign(&engine->execlist_port[0].request, NULL); @@ -2501,26 +2532,13 @@ static void i915_gem_reset_engine_cleanup(struct intel_engine_cs *engine) engine->i915->gt.active_engines &= ~intel_engine_flag(engine); } -void i915_gem_reset(struct drm_device *dev) +void i915_gem_set_wedged(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); struct intel_engine_cs *engine; - /* - * Before we free the objects from the requests, we need to inspect - * them for finding the guilty party. As the requests only borrow - * their reference to the objects, the inspection must be done first. - */ - for_each_engine(engine, dev_priv) - i915_gem_reset_engine_status(engine); - for_each_engine(engine, dev_priv) - i915_gem_reset_engine_cleanup(engine); + i915_gem_cleanup_engine(engine); mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0); - - i915_gem_context_reset(dev); - - i915_gem_restore_fences(dev); } static void @@ -4346,7 +4364,7 @@ int i915_gem_init(struct drm_device *dev) * for all other failure, such as an allocation failure, bail. */ DRM_ERROR("Failed to initialize GPU, declaring it wedged\n"); - atomic_or(I915_WEDGED, &dev_priv->gpu_error.reset_counter); + i915_gem_set_wedged(dev_priv); ret = 0; } diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index bb72af5320b0..a5b3ba4cca4a 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -405,22 +405,6 @@ static void i915_gem_context_unpin(struct i915_gem_context *ctx, } } -void i915_gem_context_reset(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - - lockdep_assert_held(&dev->struct_mutex); - - if (i915.enable_execlists) { - struct i915_gem_context *ctx; - - list_for_each_entry(ctx, &dev_priv->context_list, link) - intel_lr_context_reset(dev_priv, ctx); - } - - i915_gem_context_lost(dev_priv); -} - int i915_gem_context_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 9be71a8a1d63..e24ce2d5cf90 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1193,6 +1193,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; + intel_mocs_init_engine(engine); lrc_init_hws(engine); I915_WRITE_IMR(engine, @@ -1208,7 +1209,10 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) intel_engine_init_hangcheck(engine); - return intel_mocs_init_engine(engine); + if (engine->execlist_port[0].request) + execlists_submit_ports(engine); + + return 0; } static int gen8_init_render_ring(struct intel_engine_cs *engine) @@ -1244,6 +1248,33 @@ static int gen9_init_render_ring(struct intel_engine_cs *engine) return init_workarounds_ring(engine); } +static void reset_common_ring(struct intel_engine_cs *engine, + struct drm_i915_gem_request *request) +{ + struct drm_i915_private *dev_priv = engine->i915; + struct i915_gem_context *ctx = request->ctx; + struct intel_context *ce = &ctx->engine[engine->id]; + u32 *reg_state; + + reg_state = ce->lrc_reg_state; + reg_state[CTX_RING_HEAD+1] = request->postfix; + + request->ring->head = request->postfix; + request->ring->last_retired_head = -1; + intel_ring_update_space(request->ring); + + if (request == engine->execlist_port[1].request) { + i915_gem_request_put(engine->execlist_port[0].request); + engine->execlist_port[0] = engine->execlist_port[1]; + memset(&engine->execlist_port[1], 0, + sizeof(engine->execlist_port[1])); + } + + engine->execlist_port[0].count = 0; + + I915_WRITE(RING_CONTEXT_STATUS_PTR(engine), _MASKED_FIELD(0xffff, 0)); +} + static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) { struct i915_hw_ppgtt *ppgtt = req->ctx->ppgtt; @@ -1604,6 +1635,7 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine) { /* Default vfuncs which can be overriden by each engine. */ engine->init_hw = gen8_init_common_ring; + engine->reset_hw = reset_common_ring; engine->emit_flush = gen8_emit_flush; engine->emit_request = gen8_emit_request; engine->submit_request = execlists_submit_request; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 54ec2faa0bf2..4730b1f178fd 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -577,34 +577,31 @@ static int init_ring_common(struct intel_engine_cs *engine) if (I915_READ_HEAD(engine)) DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", engine->name, I915_READ_HEAD(engine)); - I915_WRITE_HEAD(engine, 0); - (void)I915_READ_HEAD(engine); + I915_WRITE_HEAD(engine, ring->head); + I915_WRITE_TAIL(engine, ring->tail); + (void)I915_READ_TAIL(engine); I915_WRITE_CTL(engine, ((ring->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID); /* If the head is still not zero, the ring is dead */ - if (wait_for((I915_READ_CTL(engine) & RING_VALID) != 0 && - I915_READ_START(engine) == i915_gem_obj_ggtt_offset(obj) && - (I915_READ_HEAD(engine) & HEAD_ADDR) == 0, 50)) { + if (intel_wait_for_register_fw(dev_priv, RING_CTL(engine->mmio_base), + RING_VALID, RING_VALID, + 50)) { DRM_ERROR("%s initialization failed " - "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n", + "ctl %08x (valid? %d) head %08x [%08x] tail %08x [%08x] start %08x [expected %08lx]\n", engine->name, I915_READ_CTL(engine), I915_READ_CTL(engine) & RING_VALID, - I915_READ_HEAD(engine), I915_READ_TAIL(engine), + I915_READ_HEAD(engine), ring->head, + I915_READ_TAIL(engine), ring->tail, I915_READ_START(engine), (unsigned long)i915_gem_obj_ggtt_offset(obj)); ret = -EIO; goto out; } - ring->last_retired_head = -1; - ring->head = I915_READ_HEAD(engine); - ring->tail = I915_READ_TAIL(engine) & TAIL_ADDR; - intel_ring_update_space(ring); - intel_engine_init_hangcheck(engine); out: @@ -613,6 +610,16 @@ out: return ret; } +static void reset_ring_common(struct intel_engine_cs *engine, + struct drm_i915_gem_request *request) +{ + struct intel_ring *ring = request->ring; + + ring->head = request->postfix; + ring->last_retired_head = -1; + intel_ring_update_space(ring); +} + void intel_fini_pipe_control(struct intel_engine_cs *engine) { if (engine->scratch.obj == NULL) @@ -2767,6 +2774,7 @@ static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, intel_ring_init_semaphores(dev_priv, engine); engine->init_hw = init_ring_common; + engine->reset_hw = reset_ring_common; engine->emit_request = i9xx_emit_request; if (i915.semaphores) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index a5cee335881a..092e5b27652f 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -203,6 +203,8 @@ struct intel_engine_cs { void (*irq_disable)(struct intel_engine_cs *engine); int (*init_hw)(struct intel_engine_cs *engine); + void (*reset_hw)(struct intel_engine_cs *engine, + struct drm_i915_gem_request *req); int (*init_context)(struct drm_i915_gem_request *req); -- 2.8.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx