[Intel-gfx] [PATCH 10/11] drm/i915: Allow userspace to specify ringsize on construction
Chris Wilson
chris at chris-wilson.co.uk
Thu Oct 24 11:40:27 UTC 2019
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>
---
drivers/gpu/drm/i915/gem/i915_gem_context.c | 139 +++++++++++++++++++-
drivers/gpu/drm/i915/gt/intel_lrc.c | 1 +
include/uapi/drm/i915_drm.h | 19 +++
3 files changed, 153 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 0f1bbf5d1a11..a03bee30fac1 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -520,23 +520,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 *
@@ -574,9 +581,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,
@@ -1151,6 +1159,104 @@ static int set_ppgtt(struct drm_i915_file_private *file_priv,
return err;
}
+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;
+}
+
+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 */
+}
+
+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;
+ return 0;
+}
+
static int gen8_emit_rpcs_config(struct i915_request *rq,
struct intel_context *ce,
struct intel_sseu sseu)
@@ -1863,6 +1969,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;
@@ -1931,6 +2041,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]);
+ }
}
clone->num_engines = n;
@@ -2320,6 +2443,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;
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index a7755d6dc48b..9d59debfd168 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -2309,6 +2309,7 @@ __execlists_update_reg_state(const struct intel_context *ce,
GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->tail));
regs[CTX_RING_BUFFER_START] = i915_ggtt_offset(ring->vma);
+ regs[CTX_RING_BUFFER_CONTROL] = RING_CTL_SIZE(ring->size) | RING_VALID;
regs[CTX_RING_HEAD] = ring->head;
regs[CTX_RING_TAIL] = ring->tail;
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index b5fd5e4bd16e..cd35036a26a2 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
/* Must be kept compact -- no holes and well documented */
__u64 value;
--
2.24.0.rc0
More information about the Intel-gfx
mailing list