diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_execbuffer.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_execbuffer.c | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 310601018d29..f9de86a61d42 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1151,25 +1151,19 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev, { struct intel_engine_cs *engine = req->engine; struct drm_i915_private *dev_priv = dev->dev_private; - int ret, i; + int i; if (!IS_GEN7(dev) || engine != &dev_priv->engine[RCS]) { DRM_DEBUG("sol reset is gen7/rcs only\n"); return -EINVAL; } - ret = intel_ring_begin(req, 4 * 3); - if (ret) - return ret; - for (i = 0; i < 4; i++) { intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1)); intel_ring_emit_reg(engine, GEN7_SO_WRITE_OFFSET(i)); intel_ring_emit(engine, 0); } - intel_ring_advance(engine); - return 0; } @@ -1297,6 +1291,7 @@ int i915_gem_ringbuffer_submission_final(struct i915_execbuffer_params *params) struct intel_engine_cs *engine = params->engine; u64 exec_start, exec_len; int ret; + uint32_t min_space; /* The mutex must be acquired before calling this function */ WARN_ON(!mutex_is_locked(¶ms->dev->struct_mutex)); @@ -1320,6 +1315,34 @@ int i915_gem_ringbuffer_submission_final(struct i915_execbuffer_params *params) goto error; /* + * It would be a bad idea to run out of space while writing commands + * to the ring. One of the major aims of the scheduler is to not + * stall at any point for any reason. However, doing an early exit + * half way through submission could result in a partial sequence + * being written which would leave the engine in an unknown state. + * Therefore, check in advance that there will be enough space for + * the entire submission whether emitted by the code below OR by any + * other functions that may be executed before the end of final(). + * + * NB: This test deliberately overestimates, because that's easier + * than tracing every potential path that could be taken! + * + * Current measurements suggest that we may need to emit up to 186 + * dwords, so this is rounded up to 256 here. Then double that to get + * the free space requirement, because the block is not allowed to + * span the transition from the end to the beginning of the ring. + */ +#define I915_BATCH_EXEC_MAX_LEN 256 /* max dwords emitted here */ + min_space = I915_BATCH_EXEC_MAX_LEN * 2 * sizeof(uint32_t); + ret = intel_ring_test_space(req->ringbuf, min_space); + if (ret) + goto error; + + ret = intel_ring_begin(req, I915_BATCH_EXEC_MAX_LEN); + if (ret) + goto error; + + /* * Unconditionally invalidate gpu caches and ensure that we do flush * any residual writes from the previous batch. */ @@ -1337,10 +1360,6 @@ int i915_gem_ringbuffer_submission_final(struct i915_execbuffer_params *params) if (engine == &dev_priv->engine[RCS] && params->instp_mode != dev_priv->relative_constants_mode) { - ret = intel_ring_begin(req, 4); - if (ret) - goto error; - intel_ring_emit(engine, MI_NOOP); intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1)); intel_ring_emit_reg(engine, INSTPM); |