[PATCH 24/29] drm/i915/gem: Delay context creation

Jason Ekstrand jason at jlekstrand.net
Wed Jun 2 22:55:44 UTC 2021


On Mon, May 31, 2021 at 4:50 AM Daniel Vetter <daniel at ffwll.ch> wrote:
>
> On Thu, May 27, 2021 at 11:26:45AM -0500, Jason Ekstrand wrote:
> > The current context uAPI allows for two methods of setting context
> > parameters: SET_CONTEXT_PARAM and CONTEXT_CREATE_EXT_SETPARAM.  The
> > former is allowed to be called at any time while the later happens as
> > part of GEM_CONTEXT_CREATE.  Currently, everything settable via one is
> > settable via the other.  While some params are fairly simple and setting
> > them on a live context is harmless such the context priority, others are
>
> such _as_ the

Done.

> > far trickier such as the VM or the set of engines.  In order to swap out
> > the VM, for instance, we have to delay until all current in-flight work
> > is complete, swap in the new VM, and then continue.  This leads to a
> > plethora of potential race conditions we'd really rather avoid.
> >
> > In previous patches, we added a i915_gem_proto_context struct which is
> > capable of storing and tracking all such create parameters.  This commit
> > delays the creation of the actual context until after the client is done
> > configuring it with SET_CONTEXT_PARAM.  From the perspective of the
> > client, it has the same u32 context ID the whole time.  From the
> > perspective of i915, however, it's an i915_gem_proto_context right up
> > until the point where we attempt to do something which the proto-context
> > can't handle at which point the real context gets created.
>
> s/ at which point/. Then/
>
> At least feels a bit like a run-on sentence :-)

Done.

> > This is accomplished via a little xarray dance.  When GEM_CONTEXT_CREATE
> > is called, we create a proto-context, reserve a slot in context_xa but
> > leave it NULL, the proto-context in the corresponding slot in
> > proto_context_xa.  Then, whenever we go to look up a context, we first
> > check context_xa.  If it's there, we return the i915_gem_context and
> > we're done.  If it's not, we look in proto_context_xa and, if we find it
> > there, we create the actual context and kill the proto-context.
> >
> > In order for this dance to work properly, everything which ever touches
> > a proto-context is guarded by drm_i915_file_private::proto_context_lock,
> > including context creation.  Yes, this means context creation now takes
> > a giant global lock but it can't really be helped and that should never
> > be on any driver's fast-path anyway.
> >
> > Signed-off-by: Jason Ekstrand <jason at jlekstrand.net>
> > ---
> >  drivers/gpu/drm/i915/gem/i915_gem_context.c   | 211 ++++++++++++++----
> >  drivers/gpu/drm/i915/gem/i915_gem_context.h   |   3 +
> >  .../gpu/drm/i915/gem/i915_gem_context_types.h |  54 +++++
> >  .../gpu/drm/i915/gem/selftests/mock_context.c |   5 +-
> >  drivers/gpu/drm/i915/i915_drv.h               |  24 +-
> >  5 files changed, 239 insertions(+), 58 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
> > index 8288af0d33245..f7c83730ee07f 100644
> > --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
> > @@ -298,6 +298,42 @@ proto_context_create(struct drm_i915_private *i915, unsigned int flags)
> >       return err;
> >  }
> >
> > +static int proto_context_register_locked(struct drm_i915_file_private *fpriv,
> > +                                      struct i915_gem_proto_context *pc,
> > +                                      u32 *id)
> > +{
> > +     int ret;
> > +     void *old;
> > +
> > +     lockdep_assert_held(&fpriv->proto_context_lock);
> > +
> > +     ret = xa_alloc(&fpriv->context_xa, id, NULL, xa_limit_32b, GFP_KERNEL);
> > +     if (ret)
> > +             return ret;
> > +
> > +     old = xa_store(&fpriv->proto_context_xa, *id, pc, GFP_KERNEL);
> > +     if (xa_is_err(old)) {
> > +             xa_erase(&fpriv->context_xa, *id);
> > +             return xa_err(old);
> > +     }
> > +     GEM_BUG_ON(old);
>
> I'd go with WARN_ON here. We just leak, and BUG_ON kills the box.
> GEM_BUG_ON is for the additional gem consistency checks which are too
> expensive to have enabled in production. Registering a proto context isn't
> one of these things.

Done.

> > +
> > +     return 0;
> > +}
> > +
> > +static int proto_context_register(struct drm_i915_file_private *fpriv,
> > +                               struct i915_gem_proto_context *pc,
> > +                               u32 *id)
> > +{
> > +     int ret;
> > +
> > +     mutex_lock(&fpriv->proto_context_lock);
> > +     ret = proto_context_register_locked(fpriv, pc, id);
> > +     mutex_unlock(&fpriv->proto_context_lock);
> > +
> > +     return ret;
> > +}
> > +
> >  static int set_proto_ctx_vm(struct drm_i915_file_private *fpriv,
> >                           struct i915_gem_proto_context *pc,
> >                           const struct drm_i915_gem_context_param *args)
> > @@ -1448,12 +1484,12 @@ void i915_gem_init__contexts(struct drm_i915_private *i915)
> >       init_contexts(&i915->gem.contexts);
> >  }
> >
> > -static int gem_context_register(struct i915_gem_context *ctx,
> > -                             struct drm_i915_file_private *fpriv,
> > -                             u32 *id)
> > +static void gem_context_register(struct i915_gem_context *ctx,
> > +                              struct drm_i915_file_private *fpriv,
> > +                              u32 id)
> >  {
> >       struct drm_i915_private *i915 = ctx->i915;
> > -     int ret;
> > +     void *old;
> >
> >       ctx->file_priv = fpriv;
> >
> > @@ -1462,19 +1498,12 @@ static int gem_context_register(struct i915_gem_context *ctx,
> >                current->comm, pid_nr(ctx->pid));
> >
> >       /* And finally expose ourselves to userspace via the idr */
> > -     ret = xa_alloc(&fpriv->context_xa, id, ctx, xa_limit_32b, GFP_KERNEL);
> > -     if (ret)
> > -             goto err_pid;
> > +     old = xa_store(&fpriv->context_xa, id, ctx, GFP_KERNEL);
> > +     GEM_BUG_ON(old);
>
> Same song about WARN_ON here.

Yup.

> >
> >       spin_lock(&i915->gem.contexts.lock);
> >       list_add_tail(&ctx->link, &i915->gem.contexts.list);
> >       spin_unlock(&i915->gem.contexts.lock);
> > -
> > -     return 0;
> > -
> > -err_pid:
> > -     put_pid(fetch_and_zero(&ctx->pid));
> > -     return ret;
> >  }
> >
> >  int i915_gem_context_open(struct drm_i915_private *i915,
> > @@ -1484,9 +1513,12 @@ int i915_gem_context_open(struct drm_i915_private *i915,
> >       struct i915_gem_proto_context *pc;
> >       struct i915_gem_context *ctx;
> >       int err;
> > -     u32 id;
> >
> > -     xa_init_flags(&file_priv->context_xa, XA_FLAGS_ALLOC);
> > +     mutex_init(&file_priv->proto_context_lock);
> > +     xa_init_flags(&file_priv->proto_context_xa, XA_FLAGS_ALLOC);
> > +
> > +     /* 0 reserved for the default context */
> > +     xa_init_flags(&file_priv->context_xa, XA_FLAGS_ALLOC1);
> >
> >       /* 0 reserved for invalid/unassigned ppgtt */
> >       xa_init_flags(&file_priv->vm_xa, XA_FLAGS_ALLOC1);
> > @@ -1504,28 +1536,31 @@ int i915_gem_context_open(struct drm_i915_private *i915,
> >               goto err;
> >       }
> >
> > -     err = gem_context_register(ctx, file_priv, &id);
> > -     if (err < 0)
> > -             goto err_ctx;
> > +     gem_context_register(ctx, file_priv, 0);
> >
> > -     GEM_BUG_ON(id);
> >       return 0;
> >
> > -err_ctx:
> > -     context_close(ctx);
> >  err:
> >       xa_destroy(&file_priv->vm_xa);
> >       xa_destroy(&file_priv->context_xa);
> > +     xa_destroy(&file_priv->proto_context_xa);
> > +     mutex_destroy(&file_priv->proto_context_lock);
> >       return err;
> >  }
> >
> >  void i915_gem_context_close(struct drm_file *file)
> >  {
> >       struct drm_i915_file_private *file_priv = file->driver_priv;
> > +     struct i915_gem_proto_context *pc;
> >       struct i915_address_space *vm;
> >       struct i915_gem_context *ctx;
> >       unsigned long idx;
> >
> > +     xa_for_each(&file_priv->proto_context_xa, idx, pc)
> > +             proto_context_close(pc);
> > +     xa_destroy(&file_priv->proto_context_xa);
> > +     mutex_destroy(&file_priv->proto_context_lock);
> > +
> >       xa_for_each(&file_priv->context_xa, idx, ctx)
> >               context_close(ctx);
> >       xa_destroy(&file_priv->context_xa);
> > @@ -2480,12 +2515,73 @@ static bool client_is_banned(struct drm_i915_file_private *file_priv)
> >       return atomic_read(&file_priv->ban_score) >= I915_CLIENT_SCORE_BANNED;
> >  }
> >
> > +static inline struct i915_gem_context *
> > +__context_lookup(struct drm_i915_file_private *file_priv, u32 id)
> > +{
> > +     struct i915_gem_context *ctx;
> > +
> > +     rcu_read_lock();
> > +     ctx = xa_load(&file_priv->context_xa, id);
> > +     if (ctx && !kref_get_unless_zero(&ctx->ref))
> > +             ctx = NULL;
> > +     rcu_read_unlock();
> > +
> > +     return ctx;
> > +}
> > +
> > +struct i915_gem_context *
> > +lazy_create_context_locked(struct drm_i915_file_private *file_priv,
> > +                        struct i915_gem_proto_context *pc, u32 id)
>
> My bikeshed would call this finalize_create_context_locked or something
> like that ... At least I'm thinking of this more as "finializing the
> process of creating a context" and less of "creating context on-demand".
> The latter is e.g. what we're doing with the default engine set. Different
> beasts conceptually.

Fine with me.

> > +{
> > +     struct i915_gem_context *ctx;
> > +     void *old;
> > +
> > +     lockdep_assert_held(&file_priv->proto_context_lock);
> > +
> > +     ctx = i915_gem_create_context(file_priv->dev_priv, pc);
> > +     if (IS_ERR(ctx))
> > +             return ctx;
> > +
> > +     gem_context_register(ctx, file_priv, id);
> > +
> > +     old = xa_erase(&file_priv->proto_context_xa, id);
> > +     GEM_BUG_ON(old != pc);
> > +     proto_context_close(pc);
> > +
> > +     /* One for the xarray and one for the caller */
> > +     return i915_gem_context_get(ctx);
> > +}
> > +
> > +struct i915_gem_context *
> > +i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
> > +{
> > +     struct i915_gem_proto_context *pc;
> > +     struct i915_gem_context *ctx;
> > +
> > +     ctx = __context_lookup(file_priv, id);
> > +     if (ctx)
> > +             return ctx;
> > +
> > +     mutex_lock(&file_priv->proto_context_lock);
> > +     /* Try one more time under the lock */
> > +     ctx = __context_lookup(file_priv, id);
> > +     if (!ctx) {
> > +             pc = xa_load(&file_priv->proto_context_xa, id);
> > +             if (!pc)
> > +                     ctx = ERR_PTR(-ENOENT);
> > +             else
> > +                     ctx = lazy_create_context_locked(file_priv, pc, id);
> > +     }
> > +     mutex_unlock(&file_priv->proto_context_lock);
> > +
> > +     return ctx;
> > +}
> > +
> >  int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
> >                                 struct drm_file *file)
> >  {
> >       struct drm_i915_private *i915 = to_i915(dev);
> >       struct drm_i915_gem_context_create_ext *args = data;
> > -     struct i915_gem_context *ctx;
> >       struct create_ext ext_data;
> >       int ret;
> >       u32 id;
> > @@ -2517,28 +2613,21 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
> >                                          create_extensions,
> >                                          ARRAY_SIZE(create_extensions),
> >                                          &ext_data);
> > -             if (ret) {
> > -                     proto_context_close(ext_data.pc);
> > -                     return ret;
> > -             }
> > +             if (ret)
> > +                     goto err_pc;
> >       }
> >
> > -     ctx = i915_gem_create_context(i915, ext_data.pc);
> > -     proto_context_close(ext_data.pc);
> > -     if (IS_ERR(ctx))
> > -             return PTR_ERR(ctx);
> > -
> > -     ret = gem_context_register(ctx, ext_data.fpriv, &id);
> > +     ret = proto_context_register(ext_data.fpriv, ext_data.pc, &id);
> >       if (ret < 0)
> > -             goto err_ctx;
> > +             goto err_pc;
> >
> >       args->ctx_id = id;
> >       drm_dbg(&i915->drm, "HW context %d created\n", args->ctx_id);
> >
> >       return 0;
> >
> > -err_ctx:
> > -     context_close(ctx);
> > +err_pc:
> > +     proto_context_close(ext_data.pc);
> >       return ret;
> >  }
> >
> > @@ -2547,6 +2636,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_gem_proto_context *pc;
> >       struct i915_gem_context *ctx;
> >
> >       if (args->pad != 0)
> > @@ -2555,11 +2645,21 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
> >       if (!args->ctx_id)
> >               return -ENOENT;
> >
> > +     mutex_lock(&file_priv->proto_context_lock);
>
> I think a comment here that we need to hold the proto mutex even for
> finalized context to avoid races with finalization would be nice.

Added.

> >       ctx = xa_erase(&file_priv->context_xa, args->ctx_id);
> > -     if (!ctx)
> > +     pc = xa_erase(&file_priv->proto_context_xa, args->ctx_id);
> > +     mutex_unlock(&file_priv->proto_context_lock);
> > +
> > +     if (!ctx && !pc)
> >               return -ENOENT;
> > +     GEM_WARN_ON(ctx && pc);
> > +
> > +     if (pc)
> > +             proto_context_close(pc);
> > +
> > +     if (ctx)
> > +             context_close(ctx);
> >
> > -     context_close(ctx);
> >       return 0;
> >  }
> >
> > @@ -2692,16 +2792,41 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
> >  {
> >       struct drm_i915_file_private *file_priv = file->driver_priv;
> >       struct drm_i915_gem_context_param *args = data;
> > +     struct i915_gem_proto_context *pc;
> >       struct i915_gem_context *ctx;
> > -     int ret;
> > +     int ret = 0;
> >
> > -     ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
> > -     if (IS_ERR(ctx))
> > -             return PTR_ERR(ctx);
> > +     ctx = __context_lookup(file_priv, args->ctx_id);
> > +     if (ctx)
> > +             goto set_ctx_param;
> >
> > -     ret = ctx_setparam(file_priv, ctx, args);
> > +     mutex_lock(&file_priv->proto_context_lock);
> > +     ctx = __context_lookup(file_priv, args->ctx_id);
>
> Not unconditionally taking the mutex here feels a bit like overkill? Do we
> really need that fast path?

Probably not.  If someone writes a setparam benchmark, I will actively not care.

> > +     if (ctx)
> > +             goto unlock;
> > +
> > +     pc = xa_load(&file_priv->proto_context_xa, args->ctx_id);
> > +     if (!pc) {
> > +             ret = -ENOENT;
> > +             goto unlock;
> > +     }
> > +
> > +     /* FIXME: We should consider disallowing SET_CONTEXT_PARAM for most
> > +      * things on future platforms.  Clients should be using
> > +      * CONTEXT_CREATE_EXT_PARAM instead.
> > +      */
>
> I think the way to do that is to finalize the context creation from
> CONTEXT_CREATE_EXT on these platforms. That plugs this hole for good and
> by design. Maybe on gen13+ or something like that. Or whatever it is we're
> using for enumerating generations now.

Yup.  I agree.  Do you want me to add that now?

> > +     ret = set_proto_ctx_param(file_priv, pc, args);
> > +
> > +unlock:
> > +     mutex_unlock(&file_priv->proto_context_lock);
> > +
> > +set_ctx_param:
> > +     if (!ret && ctx)
>
> I don't think you need to check for ret here? It's not set by any path
> leading to here where ctx != NULL.

I think

> Also mildly unhappy about the control flow here, we could simplify it if
> we don't do the lockless faspath.

Yeah, I think I've made it a lot better.  You may want to re-review on
the next go 'round though.

> > +             ret = ctx_setparam(file_priv, ctx, args);
> > +
> > +     if (ctx)
> > +             i915_gem_context_put(ctx);
> >
> > -     i915_gem_context_put(ctx);
> >       return ret;
> >  }
> >
> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.h b/drivers/gpu/drm/i915/gem/i915_gem_context.h
> > index b5c908f3f4f22..20411db84914a 100644
> > --- a/drivers/gpu/drm/i915/gem/i915_gem_context.h
> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.h
> > @@ -133,6 +133,9 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
> >  int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, void *data,
> >                                      struct drm_file *file);
> >
> > +struct i915_gem_context *
> > +i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id);
> > +
> >  static inline struct i915_gem_context *
> >  i915_gem_context_get(struct i915_gem_context *ctx)
> >  {
> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
> > index 2ac341f805c8f..b673061f4f5ba 100644
> > --- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
> > @@ -122,6 +122,60 @@ struct i915_gem_proto_engine {
> >   * an i915_gem_context.  This is used to gather parameters provided either
> >   * through creation flags or via SET_CONTEXT_PARAM so that, when we create
> >   * the final i915_gem_context, those parameters can be immutable.
> > + *
> > + * The context uAPI allows for two methods of setting context parameters:
> > + * SET_CONTEXT_PARAM and CONTEXT_CREATE_EXT_SETPARAM.  The former is
> > + * allowed to be called at any time while the later happens as part of
> > + * GEM_CONTEXT_CREATE.  When these were initially added, Currently,
> > + * everything settable via one is settable via the other.  While some
> > + * params are fairly simple and setting them on a live context is harmless
> > + * such the context priority, others are far trickier such as the VM or the
> > + * set of engines.  To avoid some truly nasty race conditions, we don't
> > + * allow setting the VM or the set of engines on live contexts.
> > + *
> > + * The way we dealt with this without breaking older userspace that sets
> > + * the VM or engine set via SET_CONTEXT_PARAM is to delay the creation of
> > + * the actual context until after the client is done configuring it with
> > + * SET_CONTEXT_PARAM.  From the perspective of the client, it has the same
> > + * u32 context ID the whole time.  From the perspective of i915, however,
> > + * it's an i915_gem_proto_context right up until the point where we attempt
> > + * to do something which the proto-context can't handle at which point the
> > + * real context gets created.
> > + *
> > + * This is accomplished via a little xarray dance.  When GEM_CONTEXT_CREATE
> > + * is called, we create a proto-context, reserve a slot in context_xa but
> > + * leave it NULL, the proto-context in the corresponding slot in
> > + * proto_context_xa.  Then, whenever we go to look up a context, we first
> > + * check context_xa.  If it's there, we return the i915_gem_context and
> > + * we're done.  If it's not, we look in proto_context_xa and, if we find it
> > + * there, we create the actual context and kill the proto-context.
> > + *
> > + * At the time we made this change (April, 2021), we did a fairly complete
> > + * audit of existing userspace to ensure this wouldn't break anything:
> > + *
> > + *  - Mesa/i965 didn't use the engines or VM APIs at all
> > + *
> > + *  - Mesa/ANV used the engines API but via CONTEXT_CREATE_EXT_SETPARAM and
> > + *    didn't use the VM API.
> > + *
> > + *  - Mesa/iris didn't use the engines or VM APIs at all
> > + *
> > + *  - The open-source compute-runtime didn't yet use the engines API but
> > + *    did use the VM API via SET_CONTEXT_PARAM.  However, CONTEXT_SETPARAM
> > + *    was always the second ioctl on that context, immediately following
> > + *    GEM_CONTEXT_CREATE.
> > + *
> > + *  - The media driver sets engines and bonding/balancing via
> > + *    SET_CONTEXT_PARAM.  However, CONTEXT_SETPARAM to set the VM was
> > + *    always the second ioctl on that context, immediately following
> > + *    GEM_CONTEXT_CREATE and setting engines immediately followed that.
> > + *
> > + * In order for this dance to work properly, any modification to an
> > + * i915_gem_proto_context that is exposed to the client via
> > + * drm_i915_file_private::proto_context_xa must be guarded by
> > + * drm_i915_file_private::proto_context_lock.  The exception is when a
> > + * proto-context has not yet been exposed such as when handling
> > + * CONTEXT_CREATE_SET_PARAM during GEM_CONTEXT_CREATE.
> >   */
> >  struct i915_gem_proto_context {
> >       /** @vm: See i915_gem_context::vm */
> > diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_context.c b/drivers/gpu/drm/i915/gem/selftests/mock_context.c
> > index cbeefd060e97b..61aaac4a334cf 100644
> > --- a/drivers/gpu/drm/i915/gem/selftests/mock_context.c
> > +++ b/drivers/gpu/drm/i915/gem/selftests/mock_context.c
> > @@ -81,6 +81,7 @@ void mock_init_contexts(struct drm_i915_private *i915)
> >  struct i915_gem_context *
> >  live_context(struct drm_i915_private *i915, struct file *file)
> >  {
> > +     struct drm_i915_file_private *fpriv = to_drm_file(file)->driver_priv;
> >       struct i915_gem_proto_context *pc;
> >       struct i915_gem_context *ctx;
> >       int err;
> > @@ -97,10 +98,12 @@ live_context(struct drm_i915_private *i915, struct file *file)
> >
> >       i915_gem_context_set_no_error_capture(ctx);
> >
> > -     err = gem_context_register(ctx, to_drm_file(file)->driver_priv, &id);
> > +     err = xa_alloc(&fpriv->context_xa, &id, NULL, xa_limit_32b, GFP_KERNEL);
> >       if (err < 0)
> >               goto err_ctx;
> >
> > +     gem_context_register(ctx, fpriv, id);
> > +
> >       return ctx;
> >
> >  err_ctx:
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index d7bd732ceacfc..8b00292e1ae56 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/
> > @@ -201,6 +201,16 @@ struct drm_i915_file_private {
> >               struct rcu_head rcu;
> >       };
> >
> > +     /** @proto_context_lock: Guards all i915_gem_proto_context operations
> > +      *
> > +      * See i915_gem_proto_context.
>
> Please add locking rules here, like "This is always held whenever we
> manipulate any proto context, including finalizing it on first actual use
> of the GEM context".

Done.

> > +      */
> > +     struct mutex proto_context_lock;
> > +
> > +     /** @proto_context_xa: xarray of i915_gem_proto_context */
>
> Pls fix hyperlinks.
>
> Also please put your nice explainer from the commit message here ...

Done.

> > +     struct xarray proto_context_xa;
> > +
> > +     /** @context_xa: xarray of fully created i915_gem_context */
>
> ... and reference it with a "See @proto_context_xa" here.
>
> Maybe also reference i915_gem_context_lookup() from these so readers of
> the code can easily find all the pieces of this magic.

Done.

> Also mention here that write access to @context_xa is protected by
> @proto_context_lock. It must be held to avoid races with finalization of
> proto context in e.g. i915_gem_context_destroy_ioctl(), and this wasn't
> obvious to me at all.

Done.

>
> >       struct xarray context_xa;
> >       struct xarray vm_xa;
> >
> > @@ -1857,20 +1867,6 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
> >
> >  struct dma_buf *i915_gem_prime_export(struct drm_gem_object *gem_obj, int flags);
> >
> > -static inline struct i915_gem_context *
> > -i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
> > -{
> > -     struct i915_gem_context *ctx;
> > -
> > -     rcu_read_lock();
> > -     ctx = xa_load(&file_priv->context_xa, id);
> > -     if (ctx && !kref_get_unless_zero(&ctx->ref))
> > -             ctx = NULL;
> > -     rcu_read_unlock();
> > -
> > -     return ctx ? ctx : ERR_PTR(-ENOENT);
> > -}
> > -
> >  static inline struct i915_address_space *
> >  i915_gem_vm_lookup(struct drm_i915_file_private *file_priv, u32 id)
> >  {
> > --
> > 2.31.1
>
> Nothing big looks wrong, with the nits addressed:
>
> Reviewed-by: Daniel Vetter <daniel.vetter at ffwll.ch>

If you don't mind, I'd like you to look at the new set_param logic as
well as the added comments on the next go 'round.

--Jason

> >
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch


More information about the dri-devel mailing list