summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/i915_gem_execbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_execbuffer.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c41
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(&params->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);