drm/i915: Track active engines within a context

For use in the next patch, if we track which engines have been used by
the HW, we can reduce the work required to flush our state off the HW to
those engines.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190308132522.21573-1-chris@chris-wilson.co.uk
This commit is contained in:
Chris Wilson 2019-03-08 13:25:16 +00:00
parent ab3517c1eb
commit 7e3d9a5941
7 changed files with 43 additions and 29 deletions

View File

@ -388,12 +388,9 @@ static void print_context_stats(struct seq_file *m,
struct i915_gem_context *ctx; struct i915_gem_context *ctx;
list_for_each_entry(ctx, &i915->contexts.list, link) { list_for_each_entry(ctx, &i915->contexts.list, link) {
struct intel_engine_cs *engine; struct intel_context *ce;
enum intel_engine_id id;
for_each_engine(engine, i915, id) {
struct intel_context *ce = to_intel_context(ctx, engine);
list_for_each_entry(ce, &ctx->active_engines, active_link) {
if (ce->state) if (ce->state)
per_file_stats(0, ce->state->obj, &kstats); per_file_stats(0, ce->state->obj, &kstats);
if (ce->ring) if (ce->ring)
@ -1880,9 +1877,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
{ {
struct drm_i915_private *dev_priv = node_to_i915(m->private); struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct drm_device *dev = &dev_priv->drm; struct drm_device *dev = &dev_priv->drm;
struct intel_engine_cs *engine;
struct i915_gem_context *ctx; struct i915_gem_context *ctx;
enum intel_engine_id id;
int ret; int ret;
ret = mutex_lock_interruptible(&dev->struct_mutex); ret = mutex_lock_interruptible(&dev->struct_mutex);
@ -1890,6 +1885,8 @@ static int i915_context_status(struct seq_file *m, void *unused)
return ret; return ret;
list_for_each_entry(ctx, &dev_priv->contexts.list, link) { list_for_each_entry(ctx, &dev_priv->contexts.list, link) {
struct intel_context *ce;
seq_puts(m, "HW context "); seq_puts(m, "HW context ");
if (!list_empty(&ctx->hw_id_link)) if (!list_empty(&ctx->hw_id_link))
seq_printf(m, "%x [pin %u]", ctx->hw_id, seq_printf(m, "%x [pin %u]", ctx->hw_id,
@ -1912,11 +1909,8 @@ static int i915_context_status(struct seq_file *m, void *unused)
seq_putc(m, ctx->remap_slice ? 'R' : 'r'); seq_putc(m, ctx->remap_slice ? 'R' : 'r');
seq_putc(m, '\n'); seq_putc(m, '\n');
for_each_engine(engine, dev_priv, id) { list_for_each_entry(ce, &ctx->active_engines, active_link) {
struct intel_context *ce = seq_printf(m, "%s: ", ce->engine->name);
to_intel_context(ctx, engine);
seq_printf(m, "%s: ", engine->name);
if (ce->state) if (ce->state)
describe_obj(m, ce->state->obj); describe_obj(m, ce->state->obj);
if (ce->ring) if (ce->ring)

View File

@ -226,6 +226,7 @@ static void i915_gem_context_free(struct i915_gem_context *ctx)
lockdep_assert_held(&ctx->i915->drm.struct_mutex); lockdep_assert_held(&ctx->i915->drm.struct_mutex);
GEM_BUG_ON(!i915_gem_context_is_closed(ctx)); GEM_BUG_ON(!i915_gem_context_is_closed(ctx));
GEM_BUG_ON(!list_empty(&ctx->active_engines));
release_hw_id(ctx); release_hw_id(ctx);
i915_ppgtt_put(ctx->ppgtt); i915_ppgtt_put(ctx->ppgtt);
@ -241,6 +242,7 @@ static void i915_gem_context_free(struct i915_gem_context *ctx)
put_pid(ctx->pid); put_pid(ctx->pid);
list_del(&ctx->link); list_del(&ctx->link);
mutex_destroy(&ctx->mutex);
kfree_rcu(ctx, rcu); kfree_rcu(ctx, rcu);
} }
@ -353,6 +355,7 @@ intel_context_init(struct intel_context *ce,
struct intel_engine_cs *engine) struct intel_engine_cs *engine)
{ {
ce->gem_context = ctx; ce->gem_context = ctx;
ce->engine = engine;
INIT_LIST_HEAD(&ce->signal_link); INIT_LIST_HEAD(&ce->signal_link);
INIT_LIST_HEAD(&ce->signals); INIT_LIST_HEAD(&ce->signals);
@ -381,6 +384,8 @@ __create_hw_context(struct drm_i915_private *dev_priv,
list_add_tail(&ctx->link, &dev_priv->contexts.list); list_add_tail(&ctx->link, &dev_priv->contexts.list);
ctx->i915 = dev_priv; ctx->i915 = dev_priv;
ctx->sched.priority = I915_USER_PRIORITY(I915_PRIORITY_NORMAL); ctx->sched.priority = I915_USER_PRIORITY(I915_PRIORITY_NORMAL);
INIT_LIST_HEAD(&ctx->active_engines);
mutex_init(&ctx->mutex);
for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++) for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++)
intel_context_init(&ctx->__engine[n], ctx, dev_priv->engine[n]); intel_context_init(&ctx->__engine[n], ctx, dev_priv->engine[n]);

View File

@ -163,6 +163,9 @@ struct i915_gem_context {
atomic_t hw_id_pin_count; atomic_t hw_id_pin_count;
struct list_head hw_id_link; struct list_head hw_id_link;
struct list_head active_engines;
struct mutex mutex;
/** /**
* @user_handle: userspace identifier * @user_handle: userspace identifier
* *
@ -176,7 +179,9 @@ struct i915_gem_context {
/** engine: per-engine logical HW state */ /** engine: per-engine logical HW state */
struct intel_context { struct intel_context {
struct i915_gem_context *gem_context; struct i915_gem_context *gem_context;
struct intel_engine_cs *engine;
struct intel_engine_cs *active; struct intel_engine_cs *active;
struct list_head active_link;
struct list_head signal_link; struct list_head signal_link;
struct list_head signals; struct list_head signals;
struct i915_vma *state; struct i915_vma *state;

View File

@ -1282,6 +1282,7 @@ static void execlists_context_unpin(struct intel_context *ce)
i915_gem_object_unpin_map(ce->state->obj); i915_gem_object_unpin_map(ce->state->obj);
i915_vma_unpin(ce->state); i915_vma_unpin(ce->state);
list_del(&ce->active_link);
i915_gem_context_put(ce->gem_context); i915_gem_context_put(ce->gem_context);
} }
@ -1366,6 +1367,11 @@ __execlists_context_pin(struct intel_engine_cs *engine,
__execlists_update_reg_state(engine, ce); __execlists_update_reg_state(engine, ce);
ce->state->obj->pin_global++; ce->state->obj->pin_global++;
mutex_lock(&ctx->mutex);
list_add(&ce->active_link, &ctx->active_engines);
mutex_unlock(&ctx->mutex);
i915_gem_context_get(ctx); i915_gem_context_get(ctx);
return ce; return ce;
@ -2887,9 +2893,8 @@ error_deref_obj:
void intel_lr_context_resume(struct drm_i915_private *i915) void intel_lr_context_resume(struct drm_i915_private *i915)
{ {
struct intel_engine_cs *engine;
struct i915_gem_context *ctx; struct i915_gem_context *ctx;
enum intel_engine_id id; struct intel_context *ce;
/* /*
* Because we emit WA_TAIL_DWORDS there may be a disparity * Because we emit WA_TAIL_DWORDS there may be a disparity
@ -2903,17 +2908,10 @@ void intel_lr_context_resume(struct drm_i915_private *i915)
* simplicity, we just zero everything out. * simplicity, we just zero everything out.
*/ */
list_for_each_entry(ctx, &i915->contexts.list, link) { list_for_each_entry(ctx, &i915->contexts.list, link) {
for_each_engine(engine, i915, id) { list_for_each_entry(ce, &ctx->active_engines, active_link) {
struct intel_context *ce = GEM_BUG_ON(!ce->ring);
to_intel_context(ctx, engine);
if (!ce->state)
continue;
intel_ring_reset(ce->ring, 0); intel_ring_reset(ce->ring, 0);
__execlists_update_reg_state(ce->engine, ce);
if (ce->pin_count) /* otherwise done in context_pin */
__execlists_update_reg_state(engine, ce);
} }
} }
} }

View File

@ -1431,6 +1431,7 @@ static void intel_ring_context_unpin(struct intel_context *ce)
__context_unpin_ppgtt(ce->gem_context); __context_unpin_ppgtt(ce->gem_context);
__context_unpin(ce); __context_unpin(ce);
list_del(&ce->active_link);
i915_gem_context_put(ce->gem_context); i915_gem_context_put(ce->gem_context);
} }
@ -1510,6 +1511,10 @@ __ring_context_pin(struct intel_engine_cs *engine,
{ {
int err; int err;
/* One ringbuffer to rule them all */
GEM_BUG_ON(!engine->buffer);
ce->ring = engine->buffer;
if (!ce->state && engine->context_size) { if (!ce->state && engine->context_size) {
struct i915_vma *vma; struct i915_vma *vma;
@ -1530,12 +1535,11 @@ __ring_context_pin(struct intel_engine_cs *engine,
if (err) if (err)
goto err_unpin; goto err_unpin;
mutex_lock(&ctx->mutex);
list_add(&ce->active_link, &ctx->active_engines);
mutex_unlock(&ctx->mutex);
i915_gem_context_get(ctx); i915_gem_context_get(ctx);
/* One ringbuffer to rule them all */
GEM_BUG_ON(!engine->buffer);
ce->ring = engine->buffer;
return ce; return ce;
err_unpin: err_unpin:

View File

@ -44,6 +44,8 @@ mock_context(struct drm_i915_private *i915,
INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL); INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);
INIT_LIST_HEAD(&ctx->handles_list); INIT_LIST_HEAD(&ctx->handles_list);
INIT_LIST_HEAD(&ctx->hw_id_link); INIT_LIST_HEAD(&ctx->hw_id_link);
INIT_LIST_HEAD(&ctx->active_engines);
mutex_init(&ctx->mutex);
for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++) for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++)
intel_context_init(&ctx->__engine[n], ctx, i915->engine[n]); intel_context_init(&ctx->__engine[n], ctx, i915->engine[n]);

View File

@ -125,6 +125,7 @@ static void hw_delay_complete(struct timer_list *t)
static void mock_context_unpin(struct intel_context *ce) static void mock_context_unpin(struct intel_context *ce)
{ {
mock_timeline_unpin(ce->ring->timeline); mock_timeline_unpin(ce->ring->timeline);
list_del(&ce->active_link);
i915_gem_context_put(ce->gem_context); i915_gem_context_put(ce->gem_context);
} }
@ -160,6 +161,11 @@ mock_context_pin(struct intel_engine_cs *engine,
mock_timeline_pin(ce->ring->timeline); mock_timeline_pin(ce->ring->timeline);
ce->ops = &mock_context_ops; ce->ops = &mock_context_ops;
mutex_lock(&ctx->mutex);
list_add(&ce->active_link, &ctx->active_engines);
mutex_unlock(&ctx->mutex);
i915_gem_context_get(ctx); i915_gem_context_get(ctx);
return ce; return ce;