[Intel-gfx] [PATCH 2/3] drm/i915: Allow userspace to specify ringsize on construction

Chris Wilson chris at chris-wilson.co.uk
Mon Nov 18 11:28:29 UTC 2019


Quoting Janusz Krzysztofik (2019-11-18 11:14:12)
> Hi Chris,
> 
> Only some minor comments from me, mostly out of my curiosity.
> 
> On Friday, November 15, 2019 5:05:45 PM CET Chris Wilson wrote:
> > No good reason why we must always use a static ringsize, so let
> > userspace select one during construction.
> > 
> > Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> > Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
> > ---
> > +static int __apply_ringsize(struct intel_context *ce, void *sz)
> > +{
> > +     int err;
> > +
> > +     err = i915_active_wait(&ce->active);
> > +     if (err < 0)
> > +             return err;
> > +
> > +     if (intel_context_lock_pinned(ce))
> > +             return -EINTR;
> > +
> > +     if (intel_context_is_pinned(ce)) {
> > +             err = -EBUSY; /* In active use, come back later! */
> > +             goto unlock;
> > +     }
> > +
> > +     if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
> > +             struct intel_ring *ring;
> > +
> > +             /* Replace the existing ringbuffer */
> > +             ring = intel_engine_create_ring(ce->engine,
> > +                                             (unsigned long)sz);
> > +             if (IS_ERR(ring)) {
> > +                     err = PTR_ERR(ring);
> > +                     goto unlock;
> > +             }
> > +
> > +             intel_ring_put(ce->ring);
> > +             ce->ring = ring;
> > +
> > +             /* Context image will be updated on next pin */
> > +     } else {
> > +             ce->ring = sz;
> > +     }
> > +
> > +unlock:
> > +     intel_context_unlock_pinned(ce);
> > +     return err;
> > +}
> 
> I'm wondering if this function (and __get_ringsize() below as well), with its 
> dependency on intel_context internals, especially on that dual meaning of 
> ce->ring which depends on (ce->flags & CONTEXT_ALLOC_BIT), would better fit 
> into drivers/gpu/drm/i915/gt/intel_context.c.

Possibly, but at the same time it's currently only implementing a
feature of the GEM context.

I hear you, I'm just resisting, mainly because I don't want to have to
think of a good name :)

intel_context_param.c
intel_context_ring.c

I might be able to find friends for either.

> > +static int set_ringsize(struct i915_gem_context *ctx,
> > +                     struct drm_i915_gem_context_param *args)
> > +{
> > +     if (!HAS_LOGICAL_RING_CONTEXTS(ctx->i915))
> > +             return -ENODEV;
> > +
> > +     if (args->size)
> > +             return -EINVAL;
> > +
> > +     if (!IS_ALIGNED(args->value, I915_GTT_PAGE_SIZE))
> > +             return -EINVAL;
> > +
> > +     if (args->value < I915_GTT_PAGE_SIZE)
> > +             return -EINVAL;
> > +
> > +     if (args->value > 128 * I915_GTT_PAGE_SIZE)
> > +             return -EINVAL;
> > +
> > +     return context_apply_all(ctx,
> > +                              __apply_ringsize,
> > +                              __intel_context_ring_size(args->value));
> > +}
> > +
> > +static int __get_ringsize(struct intel_context *ce, void *arg)
> > +{
> > +     int num_pages;
> > +
> > +     if (intel_context_lock_pinned(ce))
> > +             return -EINTR;
> > +
> > +     if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags))
> > +             num_pages = ce->ring->size / I915_GTT_PAGE_SIZE;
> > +     else
> > +             num_pages = (uintptr_t)ce->ring / I915_GTT_PAGE_SIZE;
> > +
> > +     intel_context_unlock_pinned(ce);
> > +     return num_pages; /* stop on first engine */
> 
> Location of this comment seems not perfect to me as it is not quite obvious 
> how that works without examining how this function is used, but having spent a 
> while looking around, I'm not able to suggest a better place.

Yeah, the comment is for the intent of returning the positive, so
there's definitely a case for explaining the unusual pattern here.

The calling loop is just a standard if (err) return err; propagation so
that hardly merits a long winded explanation.

> > +static int get_ringsize(struct i915_gem_context *ctx,
> > +                     struct drm_i915_gem_context_param *args)
> > +{
> > +     int num_pages;
> > +
> > +     if (!HAS_LOGICAL_RING_CONTEXTS(ctx->i915))
> > +             return -ENODEV;
> > +
> > +     if (args->size)
> > +             return -EINVAL;
> > +
> > +     num_pages = context_apply_all(ctx, __get_ringsize, NULL);
> > +     if (num_pages < 0)
> > +             return num_pages;
> > +
> > +     args->value = (u64)num_pages * I915_GTT_PAGE_SIZE;
> 
> Do you convert to num_pages inside __get_ringsize() then back to size in bytes 
> to avoid an overflow?  Or any other reason?  Something that may be useful in 
> the future?

Just being prudent in making sure we have sufficient bits across all the
type-narrowing.

> > @@ -2003,6 +2113,19 @@ static int clone_engines(struct i915_gem_context *dst,
> >                       __free_engines(clone, n);
> >                       goto err_unlock;
> >               }
> > +
> > +             /* Copy across the preferred ringsize */
> > +             clone->engines[n]->ring = e->engines[n]->ring;
> > +             if (test_bit(CONTEXT_ALLOC_BIT, &e->engines[n]->flags)) {
> > +                     if (intel_context_lock_pinned(e->engines[n])) {
> > +                             __free_engines(clone, n + 1);
> > +                             goto err_unlock;
> > +                     }
> > +
> > +                     clone->engines[n]->ring =
> > +                             __intel_context_ring_size(e->engines[n]->ring->size);
> > +                     intel_context_unlock_pinned(e->engines[n]);
> > +             }
> 
> Another candidate for a helper located in 
> drivers/gpu/drm/i915/gt/intel_context.c?

This is much less of a candidate for potential reuse as I feel it is very
peculiar to the GEM->engines[], and not a fit for ugpu. At least as
currently written; an intel_context_get_ring_size() to go along with
intel_context_set_ring_size(), maybe.

> > diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
> > index 5400d7e057f1..ae7cd681b075 100644
> > --- a/include/uapi/drm/i915_drm.h
> > +++ b/include/uapi/drm/i915_drm.h
> > @@ -1587,6 +1587,25 @@ struct drm_i915_gem_context_param {
> >   * By default, new contexts allow persistence.
> >   */
> >  #define I915_CONTEXT_PARAM_PERSISTENCE       0xb
> > +
> > +/*
> > + * I915_CONTEXT_PARAM_RINGSIZE:
> > + *
> > + * Sets the size of the CS ringbuffer to use for logical ring contexts. This
> > + * applies a limit of how many batches can be queued to HW before the caller
> > + * is blocked due to lack of space for more commands.
> > + *
> > + * Only reliably possible to be set prior to first use, i.e. during
> > + * construction. At any later point, the current execution must be flushed as
> > + * the ring can only be changed while the context is idle.
> > + *
> > + * Only applies to the current set of engine and lost when those engines
> > + * are replaced by a new mapping (see I915_CONTEXT_PARAM_ENGINES).
> > + *
> > + * Must be between 4 - 512 KiB, in intervals of page size [4 KiB].
> > + * Default is 16 KiB.
> > + */
> > +#define I915_CONTEXT_PARAM_RINGSIZE  0xc
> 
> I know it looked like that already before, but having other documented flags 
> separated by blank lines from each other, Is there any reason for not putting 
> another blank line after the last one?
> 
> >  /* Must be kept compact -- no holes and well documented */

You mean before the /* Must be... */? My intent is to make it conflict
and force people to take notice of the instruction.
-Chris


More information about the Intel-gfx mailing list