drm/i915: Track active engines within a context
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 8 Mar 2019 13:25:16 +0000 (13:25 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 8 Mar 2019 13:59:41 +0000 (13:59 +0000)
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
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_context.h
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/selftests/mock_context.c
drivers/gpu/drm/i915/selftests/mock_engine.c

index 0a6348ad7c98e3d1bc9bb610cf8a66899d9f3764..6a90558de213e9f43113c44241486510b9ed91a7 100644 (file)
@@ -388,12 +388,9 @@ static void print_context_stats(struct seq_file *m,
        struct i915_gem_context *ctx;
 
        list_for_each_entry(ctx, &i915->contexts.list, link) {
-               struct intel_engine_cs *engine;
-               enum intel_engine_id id;
-
-               for_each_engine(engine, i915, id) {
-                       struct intel_context *ce = to_intel_context(ctx, engine);
+               struct intel_context *ce;
 
+               list_for_each_entry(ce, &ctx->active_engines, active_link) {
                        if (ce->state)
                                per_file_stats(0, ce->state->obj, &kstats);
                        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_device *dev = &dev_priv->drm;
-       struct intel_engine_cs *engine;
        struct i915_gem_context *ctx;
-       enum intel_engine_id id;
        int ret;
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -1890,6 +1885,8 @@ static int i915_context_status(struct seq_file *m, void *unused)
                return ret;
 
        list_for_each_entry(ctx, &dev_priv->contexts.list, link) {
+               struct intel_context *ce;
+
                seq_puts(m, "HW context ");
                if (!list_empty(&ctx->hw_id_link))
                        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, '\n');
 
-               for_each_engine(engine, dev_priv, id) {
-                       struct intel_context *ce =
-                               to_intel_context(ctx, engine);
-
-                       seq_printf(m, "%s: ", engine->name);
+               list_for_each_entry(ce, &ctx->active_engines, active_link) {
+                       seq_printf(m, "%s: ", ce->engine->name);
                        if (ce->state)
                                describe_obj(m, ce->state->obj);
                        if (ce->ring)
index 486203e9d205f05a8e07de0d8de6d50d8b613540..d997695a4f77d28e2a0be763d62a3a779dcea63f 100644 (file)
@@ -226,6 +226,7 @@ static void i915_gem_context_free(struct i915_gem_context *ctx)
 
        lockdep_assert_held(&ctx->i915->drm.struct_mutex);
        GEM_BUG_ON(!i915_gem_context_is_closed(ctx));
+       GEM_BUG_ON(!list_empty(&ctx->active_engines));
 
        release_hw_id(ctx);
        i915_ppgtt_put(ctx->ppgtt);
@@ -241,6 +242,7 @@ static void i915_gem_context_free(struct i915_gem_context *ctx)
        put_pid(ctx->pid);
 
        list_del(&ctx->link);
+       mutex_destroy(&ctx->mutex);
 
        kfree_rcu(ctx, rcu);
 }
@@ -353,6 +355,7 @@ intel_context_init(struct intel_context *ce,
                   struct intel_engine_cs *engine)
 {
        ce->gem_context = ctx;
+       ce->engine = engine;
 
        INIT_LIST_HEAD(&ce->signal_link);
        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);
        ctx->i915 = dev_priv;
        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++)
                intel_context_init(&ctx->__engine[n], ctx, dev_priv->engine[n]);
index e1188d77a23d98f149bcf2e54d02dc3db8401f7c..124c2a082b993d5f3211bfb8e666722ddb7ee885 100644 (file)
@@ -163,6 +163,9 @@ struct i915_gem_context {
        atomic_t hw_id_pin_count;
        struct list_head hw_id_link;
 
+       struct list_head active_engines;
+       struct mutex mutex;
+
        /**
         * @user_handle: userspace identifier
         *
@@ -176,7 +179,9 @@ struct i915_gem_context {
        /** engine: per-engine logical HW state */
        struct intel_context {
                struct i915_gem_context *gem_context;
+               struct intel_engine_cs *engine;
                struct intel_engine_cs *active;
+               struct list_head active_link;
                struct list_head signal_link;
                struct list_head signals;
                struct i915_vma *state;
index f0ba20f2b41d5e451714120cd2c8f8ce08b6817c..a9a47dbeac88c5224442d1cfd7cc6aa7dfc5e16d 100644 (file)
@@ -1282,6 +1282,7 @@ static void execlists_context_unpin(struct intel_context *ce)
        i915_gem_object_unpin_map(ce->state->obj);
        i915_vma_unpin(ce->state);
 
+       list_del(&ce->active_link);
        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);
 
        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);
        return ce;
 
@@ -2887,9 +2893,8 @@ error_deref_obj:
 
 void intel_lr_context_resume(struct drm_i915_private *i915)
 {
-       struct intel_engine_cs *engine;
        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
@@ -2903,17 +2908,10 @@ void intel_lr_context_resume(struct drm_i915_private *i915)
         * simplicity, we just zero everything out.
         */
        list_for_each_entry(ctx, &i915->contexts.list, link) {
-               for_each_engine(engine, i915, id) {
-                       struct intel_context *ce =
-                               to_intel_context(ctx, engine);
-
-                       if (!ce->state)
-                               continue;
-
+               list_for_each_entry(ce, &ctx->active_engines, active_link) {
+                       GEM_BUG_ON(!ce->ring);
                        intel_ring_reset(ce->ring, 0);
-
-                       if (ce->pin_count) /* otherwise done in context_pin */
-                               __execlists_update_reg_state(engine, ce);
+                       __execlists_update_reg_state(ce->engine, ce);
                }
        }
 }
index 1dd0c99b893f19b140e6f8d921e930cc226c5515..82f33ff94dc87fc0cd06a883c85cf7ea1591e952 100644 (file)
@@ -1431,6 +1431,7 @@ static void intel_ring_context_unpin(struct intel_context *ce)
        __context_unpin_ppgtt(ce->gem_context);
        __context_unpin(ce);
 
+       list_del(&ce->active_link);
        i915_gem_context_put(ce->gem_context);
 }
 
@@ -1510,6 +1511,10 @@ __ring_context_pin(struct intel_engine_cs *engine,
 {
        int err;
 
+       /* One ringbuffer to rule them all */
+       GEM_BUG_ON(!engine->buffer);
+       ce->ring = engine->buffer;
+
        if (!ce->state && engine->context_size) {
                struct i915_vma *vma;
 
@@ -1530,12 +1535,11 @@ __ring_context_pin(struct intel_engine_cs *engine,
        if (err)
                goto err_unpin;
 
-       i915_gem_context_get(ctx);
-
-       /* One ringbuffer to rule them all */
-       GEM_BUG_ON(!engine->buffer);
-       ce->ring = engine->buffer;
+       mutex_lock(&ctx->mutex);
+       list_add(&ce->active_link, &ctx->active_engines);
+       mutex_unlock(&ctx->mutex);
 
+       i915_gem_context_get(ctx);
        return ce;
 
 err_unpin:
index b646cdcdd6029a95bace9ed5f537abcf28464abb..353b37b9f78e31786c94237e6527b297b92f84b4 100644 (file)
@@ -44,6 +44,8 @@ mock_context(struct drm_i915_private *i915,
        INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);
        INIT_LIST_HEAD(&ctx->handles_list);
        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++)
                intel_context_init(&ctx->__engine[n], ctx, i915->engine[n]);
index c2c954f64226cc2637d88748a698d4d891bb7fe5..8032a8a9542feff2a73214fd45802bda1aae66c2 100644 (file)
@@ -125,6 +125,7 @@ static void hw_delay_complete(struct timer_list *t)
 static void mock_context_unpin(struct intel_context *ce)
 {
        mock_timeline_unpin(ce->ring->timeline);
+       list_del(&ce->active_link);
        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);
 
        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);
        return ce;