I already got a fair review comment from Brad Volkin on this: he proposes to do this instead struct i915_hw_context { struct i915_address_space *vm; struct { struct drm_i915_gem_object *ctx_obj; struct intel_ringbuffer *ringbuf; } engine[I915_MAX_RINGS]; ... }; This is: instead of creating extra contexts with the same Context ID, modify the current i915_hw_context to work with all engines. I agree this alternative looks less *hackish*, but I want to get eyes on it (several things need careful consideration if we do this, e.g.: should the hang_stats also be per-engine?) > -----Original Message----- > From: Mateo Lozano, Oscar > Sent: Thursday, March 27, 2014 6:00 PM > To: intel-gfx@xxxxxxxxxxxxxxxxxxxxx > Cc: Mateo Lozano, Oscar > Subject: [PATCH 31/49] drm/i915/bdw: Introduce dependent contexts > > From: Oscar Mateo <oscar.mateo@xxxxxxxxx> > > From here on, we define a stand-alone context as the first context with a given > ID to be created for a new fd or a new context create ioctl. This is the one we > can easily find using integer ID management. On the other hand, dependent > contexts are subsequently created with the same ID and simply hang from the > stand-alone one. > > This patch, together with the two previous and the next, are meant to solve a > big problem we have: with execlists, we need contexts to work with all engines, > and we cannot reuse one context for more than one engine. > > Because, on a new fd or a context create ioctl, we really don't know which > engine is going to be used later on, we are going to create at that point a > "blank" context and assign it to an engine on a deferred way (during the > execbuffer, to be precise). If later on, we execbuffer on a different engine, we > create a new dependent context on the previous. > > Note: I have tried to colour this patch in a different way, using a different struct > (a "context group") to hold the context ID from where the per-engine contexts > hang, but it makes legacy contexts unnecessary complex. > > Signed-off-by: Oscar Mateo <oscar.mateo@xxxxxxxxx> > --- > drivers/gpu/drm/i915/i915_drv.h | 6 +++++- > drivers/gpu/drm/i915/i915_gem_context.c | 17 +++++++++++++-- > drivers/gpu/drm/i915/i915_lrc.c | 37 > ++++++++++++++++++++++++++++++--- > 3 files changed, 54 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h > b/drivers/gpu/drm/i915/i915_drv.h index 91b0886..d9470a4 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -602,6 +602,9 @@ struct i915_hw_context { > struct i915_address_space *vm; > > struct list_head link; > + > + /* Advanced contexts only */ > + struct list_head dependent_contexts; > }; > > struct i915_fbc { > @@ -2321,7 +2324,8 @@ int gen8_gem_context_init(struct drm_device *dev); > void gen8_gem_context_fini(struct drm_device *dev); struct i915_hw_context > *gen8_gem_create_context(struct drm_device *dev, > struct intel_engine *ring, > - struct drm_i915_file_private *file_priv, bool > create_vm); > + struct drm_i915_file_private *file_priv, > + struct i915_hw_context *standalone_ctx, bool > create_vm); > void gen8_gem_context_free(struct i915_hw_context *ctx); > > /* i915_gem_evict.c */ > diff --git a/drivers/gpu/drm/i915/i915_gem_context.c > b/drivers/gpu/drm/i915/i915_gem_context.c > index 6baa5ab..17015b2 100644 > --- a/drivers/gpu/drm/i915/i915_gem_context.c > +++ b/drivers/gpu/drm/i915/i915_gem_context.c > @@ -271,6 +271,8 @@ __create_hw_context(struct drm_device *dev, > * is no remap info, it will be a NOP. */ > ctx->remap_slice = (1 << NUM_L3_SLICES(dev)) - 1; > > + INIT_LIST_HEAD(&ctx->dependent_contexts); > + > return ctx; > > err_out: > @@ -511,6 +513,12 @@ int i915_gem_context_enable(struct > drm_i915_private *dev_priv) static int context_idr_cleanup(int id, void *p, void > *data) { > struct i915_hw_context *ctx = p; > + struct i915_hw_context *cursor, *tmp; > + > + list_for_each_entry_safe(cursor, tmp, &ctx->dependent_contexts, > dependent_contexts) { > + list_del(&cursor->dependent_contexts); > + i915_gem_context_unreference(cursor); > + } > > /* Ignore the default context because close will handle it */ > if (i915_gem_context_is_default(ctx)) > @@ -543,7 +551,7 @@ int i915_gem_context_open(struct drm_device *dev, > struct drm_file *file) > if (dev_priv->lrc_enabled) > file_priv->private_default_ctx = > gen8_gem_create_context(dev, > &dev_priv->ring[RCS], > file_priv, > - USES_FULL_PPGTT(dev)); > + NULL, > USES_FULL_PPGTT(dev)); > else > file_priv->private_default_ctx = i915_gem_create_context(dev, > file_priv, > USES_FULL_PPGTT(dev)); @@ -805,7 +813,7 @@ int > i915_gem_context_create_ioctl(struct drm_device *dev, void *data, > > if (dev_priv->lrc_enabled) > ctx = gen8_gem_create_context(dev, &dev_priv->ring[RCS], > - file_priv, USES_FULL_PPGTT(dev)); > + file_priv, NULL, > USES_FULL_PPGTT(dev)); > else > ctx = i915_gem_create_context(dev, file_priv, > USES_FULL_PPGTT(dev)); > @@ -825,6 +833,7 @@ int i915_gem_context_destroy_ioctl(struct drm_device > *dev, void *data, > struct drm_i915_gem_context_destroy *args = data; > struct drm_i915_file_private *file_priv = file->driver_priv; > struct i915_hw_context *ctx; > + struct i915_hw_context *cursor, *tmp; > int ret; > > if (args->ctx_id == DEFAULT_CONTEXT_ID) @@ -841,6 +850,10 @@ int > i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, > } > > idr_remove(&ctx->file_priv->context_idr, ctx->id); > + list_for_each_entry_safe(cursor, tmp, &ctx->dependent_contexts, > dependent_contexts) { > + list_del(&cursor->dependent_contexts); > + i915_gem_context_unreference(cursor); > + } > i915_gem_context_unreference(ctx); > mutex_unlock(&dev->struct_mutex); > > diff --git a/drivers/gpu/drm/i915/i915_lrc.c b/drivers/gpu/drm/i915/i915_lrc.c > index 124e5f2..99011cc 100644 > --- a/drivers/gpu/drm/i915/i915_lrc.c > +++ b/drivers/gpu/drm/i915/i915_lrc.c > @@ -195,23 +195,54 @@ intel_populate_lrc(struct i915_hw_context *ctx, > return 0; > } > > +static void assert_on_ppgtt_release(struct kref *kref) { > + WARN(1, "Are we trying to free the aliasing PPGTT?\n"); } > + > struct i915_hw_context * > gen8_gem_create_context(struct drm_device *dev, > struct intel_engine *ring, > struct drm_i915_file_private *file_priv, > + struct i915_hw_context *standalone_ctx, > bool create_vm) > { > struct drm_i915_private *dev_priv = dev->dev_private; > struct i915_hw_context *ctx = NULL; > struct drm_i915_gem_object *ring_obj = NULL; > struct intel_ringbuffer *ringbuf = NULL; > + bool is_dependent; > int ret; > > - ctx = i915_gem_create_context(dev, file_priv, create_vm); > + /* NB: a standalone context is the first context with a given id to be > + * created for a new fd. Dependent contexts simply hang from the > stand-alone, > + * sharing their ID and their PPGTT */ > + is_dependent = (file_priv != NULL) && (standalone_ctx != NULL); > + > + ctx = i915_gem_create_context(dev, is_dependent? NULL : file_priv, > + is_dependent? false : create_vm); > if (IS_ERR_OR_NULL(ctx)) > return ctx; > > - if (file_priv) { > + if (is_dependent) { > + struct i915_hw_ppgtt *ppgtt; > + > + /* We take the same PPGTT as the standalone */ > + ppgtt = ctx_to_ppgtt(ctx); > + kref_put(&ppgtt->ref, assert_on_ppgtt_release); > + ppgtt = ctx_to_ppgtt(standalone_ctx); > + ctx->vm = &ppgtt->base; > + kref_get(&ppgtt->ref); > + > + ctx->file_priv = file_priv; > + ctx->id = standalone_ctx->id; > + ctx->remap_slice = standalone_ctx->remap_slice; > + > + list_add_tail(&ctx->dependent_contexts, > + &standalone_ctx->dependent_contexts); > + } > + > + if (file_priv && !is_dependent) { > ret = i915_gem_obj_ggtt_pin(ctx->obj, GEN8_CONTEXT_ALIGN, > 0); > if (ret) { > DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret); @@ - > 337,7 +368,7 @@ int gen8_gem_context_init(struct drm_device *dev) > > for_each_ring(ring, dev_priv, ring_id) { > ring->default_context = gen8_gem_create_context(dev, ring, > - NULL, (ring_id == RCS)); > + NULL, NULL, (ring_id == RCS)); > if (IS_ERR_OR_NULL(ring->default_context)) { > ret = PTR_ERR(ring->default_context); > DRM_DEBUG_DRIVER("Create ctx failed: %d\n", ret); > -- > 1.9.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx