mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-04-23 05:56:14 -04:00
drm/i915/guc: Connect UAPI to GuC multi-lrc interface
Introduce 'set parallel submit' extension to connect UAPI to GuC multi-lrc interface. Kernel doc in new uAPI should explain it all. IGT: https://patchwork.freedesktop.org/patch/447008/?series=93071&rev=1 media UMD: https://github.com/intel/media-driver/pull/1252 v2: (Daniel Vetter) - Add IGT link and placeholder for media UMD link v3: (Kernel test robot) - Fix warning in unpin engines call (John Harrison) - Reword a bunch of the kernel doc v4: (John Harrison) - Add comment why perma-pin is done after setting gem context - Update some comments / docs for proto contexts v5: (John Harrison) - Rework perma-pin comment - Add BUG_IN if context is pinned when setting gem context Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Signed-off-by: Matthew Brost <matthew.brost@intel.com> Reviewed-by: John Harrison <John.C.Harrison@Intel.com> Signed-off-by: John Harrison <John.C.Harrison@Intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20211014172005.27155-17-matthew.brost@intel.com
This commit is contained in:
committed by
John Harrison
parent
d38a929449
commit
e5e32171a2
@@ -556,9 +556,150 @@ set_proto_ctx_engines_bond(struct i915_user_extension __user *base, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
set_proto_ctx_engines_parallel_submit(struct i915_user_extension __user *base,
|
||||
void *data)
|
||||
{
|
||||
struct i915_context_engines_parallel_submit __user *ext =
|
||||
container_of_user(base, typeof(*ext), base);
|
||||
const struct set_proto_ctx_engines *set = data;
|
||||
struct drm_i915_private *i915 = set->i915;
|
||||
u64 flags;
|
||||
int err = 0, n, i, j;
|
||||
u16 slot, width, num_siblings;
|
||||
struct intel_engine_cs **siblings = NULL;
|
||||
intel_engine_mask_t prev_mask;
|
||||
|
||||
/* Disabling for now */
|
||||
return -ENODEV;
|
||||
|
||||
/* FIXME: This is NIY for execlists */
|
||||
if (!(intel_uc_uses_guc_submission(&i915->gt.uc)))
|
||||
return -ENODEV;
|
||||
|
||||
if (get_user(slot, &ext->engine_index))
|
||||
return -EFAULT;
|
||||
|
||||
if (get_user(width, &ext->width))
|
||||
return -EFAULT;
|
||||
|
||||
if (get_user(num_siblings, &ext->num_siblings))
|
||||
return -EFAULT;
|
||||
|
||||
if (slot >= set->num_engines) {
|
||||
drm_dbg(&i915->drm, "Invalid placement value, %d >= %d\n",
|
||||
slot, set->num_engines);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (set->engines[slot].type != I915_GEM_ENGINE_TYPE_INVALID) {
|
||||
drm_dbg(&i915->drm,
|
||||
"Invalid placement[%d], already occupied\n", slot);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (get_user(flags, &ext->flags))
|
||||
return -EFAULT;
|
||||
|
||||
if (flags) {
|
||||
drm_dbg(&i915->drm, "Unknown flags 0x%02llx", flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(ext->mbz64); n++) {
|
||||
err = check_user_mbz(&ext->mbz64[n]);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (width < 2) {
|
||||
drm_dbg(&i915->drm, "Width (%d) < 2\n", width);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (num_siblings < 1) {
|
||||
drm_dbg(&i915->drm, "Number siblings (%d) < 1\n",
|
||||
num_siblings);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
siblings = kmalloc_array(num_siblings * width,
|
||||
sizeof(*siblings),
|
||||
GFP_KERNEL);
|
||||
if (!siblings)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Create contexts / engines */
|
||||
for (i = 0; i < width; ++i) {
|
||||
intel_engine_mask_t current_mask = 0;
|
||||
struct i915_engine_class_instance prev_engine;
|
||||
|
||||
for (j = 0; j < num_siblings; ++j) {
|
||||
struct i915_engine_class_instance ci;
|
||||
|
||||
n = i * num_siblings + j;
|
||||
if (copy_from_user(&ci, &ext->engines[n], sizeof(ci))) {
|
||||
err = -EFAULT;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
siblings[n] =
|
||||
intel_engine_lookup_user(i915, ci.engine_class,
|
||||
ci.engine_instance);
|
||||
if (!siblings[n]) {
|
||||
drm_dbg(&i915->drm,
|
||||
"Invalid sibling[%d]: { class:%d, inst:%d }\n",
|
||||
n, ci.engine_class, ci.engine_instance);
|
||||
err = -EINVAL;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (n) {
|
||||
if (prev_engine.engine_class !=
|
||||
ci.engine_class) {
|
||||
drm_dbg(&i915->drm,
|
||||
"Mismatched class %d, %d\n",
|
||||
prev_engine.engine_class,
|
||||
ci.engine_class);
|
||||
err = -EINVAL;
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
||||
prev_engine = ci;
|
||||
current_mask |= siblings[n]->logical_mask;
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
if (current_mask != prev_mask << 1) {
|
||||
drm_dbg(&i915->drm,
|
||||
"Non contiguous logical mask 0x%x, 0x%x\n",
|
||||
prev_mask, current_mask);
|
||||
err = -EINVAL;
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
prev_mask = current_mask;
|
||||
}
|
||||
|
||||
set->engines[slot].type = I915_GEM_ENGINE_TYPE_PARALLEL;
|
||||
set->engines[slot].num_siblings = num_siblings;
|
||||
set->engines[slot].width = width;
|
||||
set->engines[slot].siblings = siblings;
|
||||
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
kfree(siblings);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const i915_user_extension_fn set_proto_ctx_engines_extensions[] = {
|
||||
[I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE] = set_proto_ctx_engines_balance,
|
||||
[I915_CONTEXT_ENGINES_EXT_BOND] = set_proto_ctx_engines_bond,
|
||||
[I915_CONTEXT_ENGINES_EXT_PARALLEL_SUBMIT] =
|
||||
set_proto_ctx_engines_parallel_submit,
|
||||
};
|
||||
|
||||
static int set_proto_ctx_engines(struct drm_i915_file_private *fpriv,
|
||||
@@ -794,6 +935,7 @@ static int intel_context_set_gem(struct intel_context *ce,
|
||||
GEM_BUG_ON(rcu_access_pointer(ce->gem_context));
|
||||
RCU_INIT_POINTER(ce->gem_context, ctx);
|
||||
|
||||
GEM_BUG_ON(intel_context_is_pinned(ce));
|
||||
ce->ring_size = SZ_16K;
|
||||
|
||||
i915_vm_put(ce->vm);
|
||||
@@ -818,6 +960,25 @@ static int intel_context_set_gem(struct intel_context *ce,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __unpin_engines(struct i915_gem_engines *e, unsigned int count)
|
||||
{
|
||||
while (count--) {
|
||||
struct intel_context *ce = e->engines[count], *child;
|
||||
|
||||
if (!ce || !test_bit(CONTEXT_PERMA_PIN, &ce->flags))
|
||||
continue;
|
||||
|
||||
for_each_child(ce, child)
|
||||
intel_context_unpin(child);
|
||||
intel_context_unpin(ce);
|
||||
}
|
||||
}
|
||||
|
||||
static void unpin_engines(struct i915_gem_engines *e)
|
||||
{
|
||||
__unpin_engines(e, e->num_engines);
|
||||
}
|
||||
|
||||
static void __free_engines(struct i915_gem_engines *e, unsigned int count)
|
||||
{
|
||||
while (count--) {
|
||||
@@ -933,6 +1094,40 @@ free_engines:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int perma_pin_contexts(struct intel_context *ce)
|
||||
{
|
||||
struct intel_context *child;
|
||||
int i = 0, j = 0, ret;
|
||||
|
||||
GEM_BUG_ON(!intel_context_is_parent(ce));
|
||||
|
||||
ret = intel_context_pin(ce);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
for_each_child(ce, child) {
|
||||
ret = intel_context_pin(child);
|
||||
if (unlikely(ret))
|
||||
goto unwind;
|
||||
++i;
|
||||
}
|
||||
|
||||
set_bit(CONTEXT_PERMA_PIN, &ce->flags);
|
||||
|
||||
return 0;
|
||||
|
||||
unwind:
|
||||
intel_context_unpin(ce);
|
||||
for_each_child(ce, child) {
|
||||
if (j++ < i)
|
||||
intel_context_unpin(child);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx,
|
||||
unsigned int num_engines,
|
||||
struct i915_gem_proto_engine *pe)
|
||||
@@ -946,7 +1141,7 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx,
|
||||
e->num_engines = num_engines;
|
||||
|
||||
for (n = 0; n < num_engines; n++) {
|
||||
struct intel_context *ce;
|
||||
struct intel_context *ce, *child;
|
||||
int ret;
|
||||
|
||||
switch (pe[n].type) {
|
||||
@@ -956,7 +1151,13 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx,
|
||||
|
||||
case I915_GEM_ENGINE_TYPE_BALANCED:
|
||||
ce = intel_engine_create_virtual(pe[n].siblings,
|
||||
pe[n].num_siblings);
|
||||
pe[n].num_siblings, 0);
|
||||
break;
|
||||
|
||||
case I915_GEM_ENGINE_TYPE_PARALLEL:
|
||||
ce = intel_engine_create_parallel(pe[n].siblings,
|
||||
pe[n].num_siblings,
|
||||
pe[n].width);
|
||||
break;
|
||||
|
||||
case I915_GEM_ENGINE_TYPE_INVALID:
|
||||
@@ -977,6 +1178,30 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx,
|
||||
err = ERR_PTR(ret);
|
||||
goto free_engines;
|
||||
}
|
||||
for_each_child(ce, child) {
|
||||
ret = intel_context_set_gem(child, ctx, pe->sseu);
|
||||
if (ret) {
|
||||
err = ERR_PTR(ret);
|
||||
goto free_engines;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: Must be done after calling intel_context_set_gem as that
|
||||
* function changes the ring size. The ring is allocated when
|
||||
* the context is pinned. If the ring size is changed after
|
||||
* allocation we have a mismatch of the ring size and will cause
|
||||
* the context to hang. Presumably with a bit of reordering we
|
||||
* could move the perma-pin step to the backend function
|
||||
* intel_engine_create_parallel.
|
||||
*/
|
||||
if (pe[n].type == I915_GEM_ENGINE_TYPE_PARALLEL) {
|
||||
ret = perma_pin_contexts(ce);
|
||||
if (ret) {
|
||||
err = ERR_PTR(ret);
|
||||
goto free_engines;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return e;
|
||||
@@ -1219,6 +1444,7 @@ static void context_close(struct i915_gem_context *ctx)
|
||||
|
||||
/* Flush any concurrent set_engines() */
|
||||
mutex_lock(&ctx->engines_mutex);
|
||||
unpin_engines(__context_engines_static(ctx));
|
||||
engines_idle_release(ctx, rcu_replace_pointer(ctx->engines, NULL, 1));
|
||||
i915_gem_context_set_closed(ctx);
|
||||
mutex_unlock(&ctx->engines_mutex);
|
||||
|
||||
Reference in New Issue
Block a user