Commit 5f19e2bf authored by John Harrison's avatar John Harrison Committed by Daniel Vetter

drm/i915: Merged the many do_execbuf() parameters into a structure

The do_execbuf() function takes quite a few parameters. The actual set of
parameters is going to change with the conversion to passing requests around.
Further, it is due to grow massively with the arrival of the GPU scheduler.

This patch simplifies the prototype by passing a parameter structure instead.
Changing the parameter set in the future is then simply a matter of
adding/removing items to the structure.

Note that the structure does not contain absolutely everything that is passed
in. This is because the intention is to use this structure more extensively
later in this patch series and more especially in the GPU scheduler that is
coming soon. The latter requires hanging on to the structure as the final
hardware submission can be delayed until long after the execbuf IOCTL has
returned to user land. Thus it is unsafe to put anything in the structure that
is local to the IOCTL call itself - such as the 'args' parameter. All entries
must be copies of data or pointers to structures that are reference counted in
some way and guaranteed to exist for the duration of the batch buffer's life.

v2: Rebased to newer tree and updated for changes to the command parser.
Specifically, a code shuffle has required saving the batch start address in the
params structure.

For: VIZ-5115
Signed-off-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Reviewed-by: default avatarTomas Elf <tomas.elf@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 40e895ce
...@@ -1648,6 +1648,17 @@ struct i915_virtual_gpu { ...@@ -1648,6 +1648,17 @@ struct i915_virtual_gpu {
bool active; bool active;
}; };
struct i915_execbuffer_params {
struct drm_device *dev;
struct drm_file *file;
uint32_t dispatch_flags;
uint32_t args_batch_start_offset;
uint32_t batch_obj_vm_offset;
struct intel_engine_cs *ring;
struct drm_i915_gem_object *batch_obj;
struct intel_context *ctx;
};
struct drm_i915_private { struct drm_i915_private {
struct drm_device *dev; struct drm_device *dev;
struct kmem_cache *objects; struct kmem_cache *objects;
...@@ -1885,13 +1896,9 @@ struct drm_i915_private { ...@@ -1885,13 +1896,9 @@ struct drm_i915_private {
/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
struct { struct {
int (*execbuf_submit)(struct drm_device *dev, struct drm_file *file, int (*execbuf_submit)(struct i915_execbuffer_params *params,
struct intel_engine_cs *ring,
struct intel_context *ctx,
struct drm_i915_gem_execbuffer2 *args, struct drm_i915_gem_execbuffer2 *args,
struct list_head *vmas, struct list_head *vmas);
struct drm_i915_gem_object *batch_obj,
u64 exec_start, u32 flags);
int (*init_rings)(struct drm_device *dev); int (*init_rings)(struct drm_device *dev);
void (*cleanup_ring)(struct intel_engine_cs *ring); void (*cleanup_ring)(struct intel_engine_cs *ring);
void (*stop_ring)(struct intel_engine_cs *ring); void (*stop_ring)(struct intel_engine_cs *ring);
...@@ -2689,14 +2696,9 @@ void i915_gem_execbuffer_retire_commands(struct drm_device *dev, ...@@ -2689,14 +2696,9 @@ void i915_gem_execbuffer_retire_commands(struct drm_device *dev,
struct drm_file *file, struct drm_file *file,
struct intel_engine_cs *ring, struct intel_engine_cs *ring,
struct drm_i915_gem_object *obj); struct drm_i915_gem_object *obj);
int i915_gem_ringbuffer_submission(struct drm_device *dev, int i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
struct drm_file *file,
struct intel_engine_cs *ring,
struct intel_context *ctx,
struct drm_i915_gem_execbuffer2 *args, struct drm_i915_gem_execbuffer2 *args,
struct list_head *vmas, struct list_head *vmas);
struct drm_i915_gem_object *batch_obj,
u64 exec_start, u32 flags);
int i915_gem_execbuffer(struct drm_device *dev, void *data, int i915_gem_execbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
int i915_gem_execbuffer2(struct drm_device *dev, void *data, int i915_gem_execbuffer2(struct drm_device *dev, void *data,
......
...@@ -1193,17 +1193,15 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *ring, ...@@ -1193,17 +1193,15 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *ring,
} }
int int
i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
struct intel_engine_cs *ring,
struct intel_context *ctx,
struct drm_i915_gem_execbuffer2 *args, struct drm_i915_gem_execbuffer2 *args,
struct list_head *vmas, struct list_head *vmas)
struct drm_i915_gem_object *batch_obj,
u64 exec_start, u32 dispatch_flags)
{ {
struct drm_clip_rect *cliprects = NULL; struct drm_clip_rect *cliprects = NULL;
struct drm_device *dev = params->dev;
struct intel_engine_cs *ring = params->ring;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u64 exec_len; u64 exec_start, exec_len;
int instp_mode; int instp_mode;
u32 instp_mask; u32 instp_mask;
int i, ret = 0; int i, ret = 0;
...@@ -1255,11 +1253,11 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, ...@@ -1255,11 +1253,11 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,
if (ret) if (ret)
goto error; goto error;
ret = i915_switch_context(ring, ctx); ret = i915_switch_context(ring, params->ctx);
if (ret) if (ret)
goto error; goto error;
WARN(ctx->ppgtt && ctx->ppgtt->pd_dirty_rings & (1<<ring->id), WARN(params->ctx->ppgtt && params->ctx->ppgtt->pd_dirty_rings & (1<<ring->id),
"%s didn't clear reload\n", ring->name); "%s didn't clear reload\n", ring->name);
instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK; instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK;
...@@ -1320,7 +1318,10 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, ...@@ -1320,7 +1318,10 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,
goto error; goto error;
} }
exec_len = args->batch_len; exec_len = args->batch_len;
exec_start = params->batch_obj_vm_offset +
params->args_batch_start_offset;
if (cliprects) { if (cliprects) {
for (i = 0; i < args->num_cliprects; i++) { for (i = 0; i < args->num_cliprects; i++) {
ret = i915_emit_box(ring, &cliprects[i], ret = i915_emit_box(ring, &cliprects[i],
...@@ -1330,22 +1331,23 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, ...@@ -1330,22 +1331,23 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,
ret = ring->dispatch_execbuffer(ring, ret = ring->dispatch_execbuffer(ring,
exec_start, exec_len, exec_start, exec_len,
dispatch_flags); params->dispatch_flags);
if (ret) if (ret)
goto error; goto error;
} }
} else { } else {
ret = ring->dispatch_execbuffer(ring, ret = ring->dispatch_execbuffer(ring,
exec_start, exec_len, exec_start, exec_len,
dispatch_flags); params->dispatch_flags);
if (ret) if (ret)
return ret; return ret;
} }
trace_i915_gem_ring_dispatch(intel_ring_get_request(ring), dispatch_flags); trace_i915_gem_ring_dispatch(intel_ring_get_request(ring), params->dispatch_flags);
i915_gem_execbuffer_move_to_active(vmas, ring); i915_gem_execbuffer_move_to_active(vmas, ring);
i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj); i915_gem_execbuffer_retire_commands(params->dev, params->file, ring,
params->batch_obj);
error: error:
kfree(cliprects); kfree(cliprects);
...@@ -1415,8 +1417,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, ...@@ -1415,8 +1417,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
struct intel_engine_cs *ring; struct intel_engine_cs *ring;
struct intel_context *ctx; struct intel_context *ctx;
struct i915_address_space *vm; struct i915_address_space *vm;
struct i915_execbuffer_params params_master; /* XXX: will be removed later */
struct i915_execbuffer_params *params = &params_master;
const u32 ctx_id = i915_execbuffer2_get_context_id(*args); const u32 ctx_id = i915_execbuffer2_get_context_id(*args);
u64 exec_start = args->batch_start_offset;
u32 dispatch_flags; u32 dispatch_flags;
int ret; int ret;
bool need_relocs; bool need_relocs;
...@@ -1509,6 +1512,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, ...@@ -1509,6 +1512,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
else else
vm = &dev_priv->gtt.base; vm = &dev_priv->gtt.base;
memset(&params_master, 0x00, sizeof(params_master));
eb = eb_create(args); eb = eb_create(args);
if (eb == NULL) { if (eb == NULL) {
i915_gem_context_unreference(ctx); i915_gem_context_unreference(ctx);
...@@ -1551,6 +1556,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, ...@@ -1551,6 +1556,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
goto err; goto err;
} }
params->args_batch_start_offset = args->batch_start_offset;
if (i915_needs_cmd_parser(ring) && args->batch_len) { if (i915_needs_cmd_parser(ring) && args->batch_len) {
struct drm_i915_gem_object *parsed_batch_obj; struct drm_i915_gem_object *parsed_batch_obj;
...@@ -1582,7 +1588,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, ...@@ -1582,7 +1588,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
* command parser has accepted. * command parser has accepted.
*/ */
dispatch_flags |= I915_DISPATCH_SECURE; dispatch_flags |= I915_DISPATCH_SECURE;
exec_start = 0; params->args_batch_start_offset = 0;
batch_obj = parsed_batch_obj; batch_obj = parsed_batch_obj;
} }
} }
...@@ -1607,18 +1613,29 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, ...@@ -1607,18 +1613,29 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
if (ret) if (ret)
goto err; goto err;
exec_start += i915_gem_obj_ggtt_offset(batch_obj); params->batch_obj_vm_offset = i915_gem_obj_ggtt_offset(batch_obj);
} else } else
exec_start += i915_gem_obj_offset(batch_obj, vm); params->batch_obj_vm_offset = i915_gem_obj_offset(batch_obj, vm);
/* Allocate a request for this batch buffer nice and early. */ /* Allocate a request for this batch buffer nice and early. */
ret = i915_gem_request_alloc(ring, ctx); ret = i915_gem_request_alloc(ring, ctx);
if (ret) if (ret)
goto err_batch_unpin; goto err_batch_unpin;
ret = dev_priv->gt.execbuf_submit(dev, file, ring, ctx, args, /*
&eb->vmas, batch_obj, exec_start, * Save assorted stuff away to pass through to *_submission().
dispatch_flags); * NB: This data should be 'persistent' and not local as it will
* kept around beyond the duration of the IOCTL once the GPU
* scheduler arrives.
*/
params->dev = dev;
params->file = file;
params->ring = ring;
params->dispatch_flags = dispatch_flags;
params->batch_obj = batch_obj;
params->ctx = ctx;
ret = dev_priv->gt.execbuf_submit(params, args, &eb->vmas);
err_batch_unpin: err_batch_unpin:
/* /*
......
...@@ -858,16 +858,15 @@ static int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf, ...@@ -858,16 +858,15 @@ static int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf,
* *
* Return: non-zero if the submission fails. * Return: non-zero if the submission fails.
*/ */
int intel_execlists_submission(struct drm_device *dev, struct drm_file *file, int intel_execlists_submission(struct i915_execbuffer_params *params,
struct intel_engine_cs *ring,
struct intel_context *ctx,
struct drm_i915_gem_execbuffer2 *args, struct drm_i915_gem_execbuffer2 *args,
struct list_head *vmas, struct list_head *vmas)
struct drm_i915_gem_object *batch_obj,
u64 exec_start, u32 dispatch_flags)
{ {
struct drm_device *dev = params->dev;
struct intel_engine_cs *ring = params->ring;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf; struct intel_ringbuffer *ringbuf = params->ctx->engine[ring->id].ringbuf;
u64 exec_start;
int instp_mode; int instp_mode;
u32 instp_mask; u32 instp_mask;
int ret; int ret;
...@@ -918,13 +917,13 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file, ...@@ -918,13 +917,13 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file,
return -EINVAL; return -EINVAL;
} }
ret = execlists_move_to_gpu(ringbuf, ctx, vmas); ret = execlists_move_to_gpu(ringbuf, params->ctx, vmas);
if (ret) if (ret)
return ret; return ret;
if (ring == &dev_priv->ring[RCS] && if (ring == &dev_priv->ring[RCS] &&
instp_mode != dev_priv->relative_constants_mode) { instp_mode != dev_priv->relative_constants_mode) {
ret = intel_logical_ring_begin(ringbuf, ctx, 4); ret = intel_logical_ring_begin(ringbuf, params->ctx, 4);
if (ret) if (ret)
return ret; return ret;
...@@ -937,14 +936,17 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file, ...@@ -937,14 +936,17 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file,
dev_priv->relative_constants_mode = instp_mode; dev_priv->relative_constants_mode = instp_mode;
} }
ret = ring->emit_bb_start(ringbuf, ctx, exec_start, dispatch_flags); exec_start = params->batch_obj_vm_offset +
args->batch_start_offset;
ret = ring->emit_bb_start(ringbuf, params->ctx, exec_start, params->dispatch_flags);
if (ret) if (ret)
return ret; return ret;
trace_i915_gem_ring_dispatch(intel_ring_get_request(ring), dispatch_flags); trace_i915_gem_ring_dispatch(intel_ring_get_request(ring), params->dispatch_flags);
i915_gem_execbuffer_move_to_active(vmas, ring); i915_gem_execbuffer_move_to_active(vmas, ring);
i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj); i915_gem_execbuffer_retire_commands(params->dev, params->file, ring, params->batch_obj);
return 0; return 0;
} }
......
...@@ -76,13 +76,10 @@ void intel_lr_context_reset(struct drm_device *dev, ...@@ -76,13 +76,10 @@ void intel_lr_context_reset(struct drm_device *dev,
/* Execlists */ /* Execlists */
int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists); int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists);
int intel_execlists_submission(struct drm_device *dev, struct drm_file *file, struct i915_execbuffer_params;
struct intel_engine_cs *ring, int intel_execlists_submission(struct i915_execbuffer_params *params,
struct intel_context *ctx,
struct drm_i915_gem_execbuffer2 *args, struct drm_i915_gem_execbuffer2 *args,
struct list_head *vmas, struct list_head *vmas);
struct drm_i915_gem_object *batch_obj,
u64 exec_start, u32 dispatch_flags);
u32 intel_execlists_ctx_id(struct drm_i915_gem_object *ctx_obj); u32 intel_execlists_ctx_id(struct drm_i915_gem_object *ctx_obj);
void intel_lrc_irq_handler(struct intel_engine_cs *ring); void intel_lrc_irq_handler(struct intel_engine_cs *ring);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment