Skip to content

Commit

Permalink
drm/i915: Allow userspace to specify ringsize on construction
Browse files Browse the repository at this point in the history
No good reason why we must always use a static ringsize, so let
userspace select one during construction.

Link: intel/compute-runtime#261
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Steve Carbonari <steven.carbonari@intel.com>
Reviewed-by: Janusz Krzysztofik <janusz.krzysztofik@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200225192206.1107336-2-chris@chris-wilson.co.uk
  • Loading branch information
ickle authored and wulf7 committed Nov 30, 2021
1 parent a582f0c commit ccebc70
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 8 deletions.
110 changes: 102 additions & 8 deletions drivers/gpu/drm/i915/gem/i915_gem_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@

#include "gt/gen6_ppgtt.h"
#include "gt/intel_context.h"
#include "gt/intel_context_param.h"
#include "gt/intel_engine_heartbeat.h"
#include "gt/intel_engine_user.h"
#include "gt/intel_ring.h"
Expand Down Expand Up @@ -668,23 +669,30 @@ __create_context(struct drm_i915_private *i915)
return ERR_PTR(err);
}

static void
static int
context_apply_all(struct i915_gem_context *ctx,
void (*fn)(struct intel_context *ce, void *data),
int (*fn)(struct intel_context *ce, void *data),
void *data)
{
struct i915_gem_engines_iter it;
struct intel_context *ce;
int err = 0;

for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it)
fn(ce, data);
for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) {
err = fn(ce, data);
if (err)
break;
}
i915_gem_context_unlock_engines(ctx);

return err;
}

static void __apply_ppgtt(struct intel_context *ce, void *vm)
static int __apply_ppgtt(struct intel_context *ce, void *vm)
{
i915_vm_put(ce->vm);
ce->vm = i915_vm_get(vm);
return 0;
}

static struct i915_address_space *
Expand Down Expand Up @@ -722,9 +730,10 @@ static void __set_timeline(struct intel_timeline **dst,
intel_timeline_put(old);
}

static void __apply_timeline(struct intel_context *ce, void *timeline)
static int __apply_timeline(struct intel_context *ce, void *timeline)
{
__set_timeline(&ce->timeline, timeline);
return 0;
}

static void __assign_timeline(struct i915_gem_context *ctx,
Expand Down Expand Up @@ -1219,6 +1228,63 @@ static int set_ppgtt(struct drm_i915_file_private *file_priv,
return err;
}

static int __apply_ringsize(struct intel_context *ce, void *sz)
{
return intel_context_set_ring_size(ce, (unsigned long)sz);
}

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)
{
long sz;

sz = intel_context_get_ring_size(ce);
GEM_BUG_ON(sz > INT_MAX);

return sz; /* stop on first engine */
}

static int get_ringsize(struct i915_gem_context *ctx,
struct drm_i915_gem_context_param *args)
{
int sz;

if (!HAS_LOGICAL_RING_CONTEXTS(ctx->i915))
return -ENODEV;

if (args->size)
return -EINVAL;

sz = context_apply_all(ctx, __get_ringsize, NULL);
if (sz < 0)
return sz;

args->value = sz;
return 0;
}

static int
user_to_context_sseu(struct drm_i915_private *i915,
const struct drm_i915_gem_context_param_sseu *user,
Expand Down Expand Up @@ -1856,17 +1922,19 @@ set_persistence(struct i915_gem_context *ctx,
return __context_set_persistence(ctx, args->value);
}

static void __apply_priority(struct intel_context *ce, void *arg)
static int __apply_priority(struct intel_context *ce, void *arg)
{
struct i915_gem_context *ctx = arg;

if (!intel_engine_has_semaphores(ce->engine))
return;
return 0;

if (ctx->sched.priority >= I915_PRIORITY_NORMAL)
intel_context_set_use_semaphores(ce);
else
intel_context_clear_use_semaphores(ce);

return 0;
}

static int set_priority(struct i915_gem_context *ctx,
Expand Down Expand Up @@ -1959,6 +2027,10 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv,
ret = set_persistence(ctx, args);
break;

case I915_CONTEXT_PARAM_RINGSIZE:
ret = set_ringsize(ctx, args);
break;

case I915_CONTEXT_PARAM_BAN_PERIOD:
default:
ret = -EINVAL;
Expand Down Expand Up @@ -1987,6 +2059,18 @@ static int create_setparam(struct i915_user_extension __user *ext, void *data)
return ctx_setparam(arg->fpriv, arg->ctx, &local.param);
}

static int copy_ring_size(struct intel_context *dst,
struct intel_context *src)
{
long sz;

sz = intel_context_get_ring_size(src);
if (sz < 0)
return sz;

return intel_context_set_ring_size(dst, sz);
}

static int clone_engines(struct i915_gem_context *dst,
struct i915_gem_context *src)
{
Expand Down Expand Up @@ -2030,6 +2114,12 @@ static int clone_engines(struct i915_gem_context *dst,
}

intel_context_set_gem(clone->engines[n], dst);

/* Copy across the preferred ringsize */
if (copy_ring_size(clone->engines[n], e->engines[n])) {
__free_engines(clone, n + 1);
goto err_unlock;
}
}
clone->num_engines = n;

Expand Down Expand Up @@ -2392,6 +2482,10 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
args->value = i915_gem_context_is_persistent(ctx);
break;

case I915_CONTEXT_PARAM_RINGSIZE:
ret = get_ringsize(ctx, args);
break;

case I915_CONTEXT_PARAM_BAN_PERIOD:
default:
ret = -EINVAL;
Expand Down
63 changes: 63 additions & 0 deletions drivers/gpu/drm/i915/gt/intel_context_param.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: MIT
/*
* Copyright © 2019 Intel Corporation
*/

#include "i915_active.h"
#include "intel_context.h"
#include "intel_context_param.h"
#include "intel_ring.h"

int intel_context_set_ring_size(struct intel_context *ce, long sz)
{
int err;

if (intel_context_lock_pinned(ce))
return -EINTR;

err = i915_active_wait(&ce->active);
if (err < 0)
goto unlock;

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, 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 = __intel_context_ring_size(sz);
}

unlock:
intel_context_unlock_pinned(ce);
return err;
}

long intel_context_get_ring_size(struct intel_context *ce)
{
long sz = (unsigned long)READ_ONCE(ce->ring);

if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
if (intel_context_lock_pinned(ce))
return -EINTR;

sz = ce->ring->size;
intel_context_unlock_pinned(ce);
}

return sz;
}
14 changes: 14 additions & 0 deletions drivers/gpu/drm/i915/gt/intel_context_param.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2019 Intel Corporation
*/

#ifndef INTEL_CONTEXT_PARAM_H
#define INTEL_CONTEXT_PARAM_H

struct intel_context;

int intel_context_set_ring_size(struct intel_context *ce, long sz);
long intel_context_get_ring_size(struct intel_context *ce);

#endif /* INTEL_CONTEXT_PARAM_H */
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/gt/intel_lrc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2970,6 +2970,7 @@ __execlists_update_reg_state(const struct intel_context *ce,
regs[CTX_RING_START] = i915_ggtt_offset(ring->vma);
regs[CTX_RING_HEAD] = head;
regs[CTX_RING_TAIL] = ring->tail;
regs[CTX_RING_CTL] = RING_CTL_SIZE(ring->size) | RING_VALID;

/* RPCS */
if (engine->class == RENDER_CLASS) {
Expand Down
1 change: 1 addition & 0 deletions i915/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ SRCS+= debugfs_engines.c \
gen9_renderstate.c \
intel_breadcrumbs.c \
intel_context.c \
intel_context_param.c \
intel_context_sseu.c \
intel_engine_cs.c \
intel_engine_heartbeat.c \
Expand Down
21 changes: 21 additions & 0 deletions include/uapi/drm/i915_drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1619,6 +1619,27 @@ 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. Note, the ringsize
* can be specified as a constructor property, see
* I915_CONTEXT_CREATE_EXT_SETPARAM, but can also be set later if required.
*
* 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
/* Must be kept compact -- no holes and well documented */

__u64 value;
Expand Down

0 comments on commit ccebc70

Please sign in to comment.