diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_context.c | 124 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_context.h | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lrc.c | 29 | ||||
-rw-r--r-- | include/uapi/drm/i915_drm.h | 3 |
4 files changed, 129 insertions, 57 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 1ddaa8a58855..e9a1afb07912 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -926,11 +926,66 @@ out: return 0; } +static bool ctx_has_veng(struct i915_gem_context *ctx) +{ + return ctx->engines && ctx->engines[0] && + (ctx->engines[0]->flags & I915_ENGINE_IS_VIRTUAL); +} + +static bool ctx_has_map(struct i915_gem_context *ctx) +{ + return ctx->engines; +} + +static struct intel_context * +ctx_sseu_lookup_context(struct i915_gem_context *ctx, + const struct drm_i915_gem_context_param_sseu *user_sseu) +{ + struct intel_engine_cs *engine = NULL; + struct intel_context *ce = NULL; + + if (user_sseu->flags & I915_SSEU_USE_ENGINE_MAP_INDEX) { + struct virtual_engine *ve; + + if (!ctx_has_map(ctx) || + user_sseu->engine_class != (u16)I915_ENGINE_CLASS_INVALID) + return NULL; + + if (user_sseu->engine_instance == 0) { + unsigned int i; + + if (!ctx_has_veng(ctx)) + return NULL; + + for (i = 1; i < ctx->nengine; i++) { + if (ctx->engines[i]->class != RENDER_CLASS) + return NULL; + } + + ve = to_virtual_engine(ctx->engines[0]); + ce = &ve->context; + } else { + if (user_sseu->engine_instance >= ctx->nengine) + return NULL; + + engine = ctx->engines[user_sseu->engine_instance]; + } + } else { + engine = intel_engine_lookup_user(ctx->i915, + user_sseu->engine_class, + user_sseu->engine_instance); + } + + if (!ce && engine) + return to_intel_context(ctx, engine); + else + return ce; +} + static int get_sseu(struct i915_gem_context *ctx, struct drm_i915_gem_context_param *args) { struct drm_i915_gem_context_param_sseu user_sseu; - struct intel_engine_cs *engine; struct intel_context *ce; int ret; @@ -943,13 +998,10 @@ static int get_sseu(struct i915_gem_context *ctx, sizeof(user_sseu))) return -EFAULT; - if (user_sseu.flags || user_sseu.rsvd) + if (user_sseu.rsvd) return -EINVAL; - engine = intel_engine_lookup_user(ctx->i915, - user_sseu.engine_class, - user_sseu.engine_instance); - if (!engine) + if (user_sseu.flags & ~I915_SSEU_USE_ENGINE_MAP_INDEX) return -EINVAL; /* Only use for mutex here is to serialize get_param and set_param. */ @@ -957,7 +1009,11 @@ static int get_sseu(struct i915_gem_context *ctx, if (ret) return ret; - ce = to_intel_context(ctx, engine); + ce = ctx_sseu_lookup_context(ctx, &user_sseu); + if (!ce) { + ret = -EINVAL; + goto err_unlock; + } user_sseu.slice_mask = ce->sseu.slice_mask; user_sseu.subslice_mask = ce->sseu.subslice_mask; @@ -974,6 +1030,11 @@ out: args->size = sizeof(user_sseu); return 0; + +err_unlock: + mutex_unlock(&ctx->i915->drm.struct_mutex); + + return ret; } int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data, @@ -1261,11 +1322,10 @@ static int gen8_emit_rpcs_config(struct i915_request *rq, } static int -gen8_modify_rpcs_gpu(struct intel_context *ce, - struct intel_engine_cs *engine, - struct intel_sseu sseu) +gen8_modify_rpcs_gpu(struct intel_context *ce, struct intel_sseu sseu) { - struct drm_i915_private *i915 = engine->i915; + struct drm_i915_private *i915 = ce->gem_context->i915; + struct intel_engine_cs *engine; struct i915_request *rq, *prev; intel_wakeref_t wakeref; int ret; @@ -1274,6 +1334,13 @@ gen8_modify_rpcs_gpu(struct intel_context *ce, lockdep_assert_held(&i915->drm.struct_mutex); + if (ce->owner->flags & I915_ENGINE_IS_VIRTUAL) + engine = ce->gem_context->engines[1]; + else + engine = ce->owner; + + GEM_BUG_ON(engine->class != RENDER_CLASS); + /* Submitting requests etc needs the hw awake. */ wakeref = intel_runtime_pm_get(i915); @@ -1321,17 +1388,15 @@ out_put: } static int -i915_gem_context_reconfigure_sseu(struct i915_gem_context *ctx, - struct intel_engine_cs *engine, +i915_gem_context_reconfigure_sseu(struct intel_context *ce, struct intel_sseu sseu) { - struct intel_context *ce = to_intel_context(ctx, engine); + struct drm_i915_private *i915 = ce->gem_context->i915; int ret; - GEM_BUG_ON(INTEL_GEN(ctx->i915) < 8); - GEM_BUG_ON(engine->id != RCS); + GEM_BUG_ON(INTEL_GEN(i915) < 8); - ret = mutex_lock_interruptible(&ctx->i915->drm.struct_mutex); + ret = mutex_lock_interruptible(&i915->drm.struct_mutex); if (ret) return ret; @@ -1345,13 +1410,13 @@ i915_gem_context_reconfigure_sseu(struct i915_gem_context *ctx, * will be configured on pinning. */ if (ce->pin_count) - ret = gen8_modify_rpcs_gpu(ce, engine, sseu); + ret = gen8_modify_rpcs_gpu(ce, sseu); if (!ret) ce->sseu = sseu; out: - mutex_unlock(&ctx->i915->drm.struct_mutex); + mutex_unlock(&i915->drm.struct_mutex); return ret; } @@ -1461,7 +1526,7 @@ static int set_sseu(struct i915_gem_context *ctx, { struct drm_i915_private *i915 = ctx->i915; struct drm_i915_gem_context_param_sseu user_sseu; - struct intel_engine_cs *engine; + struct intel_context *ce; struct intel_sseu sseu; int ret; @@ -1475,24 +1540,29 @@ static int set_sseu(struct i915_gem_context *ctx, sizeof(user_sseu))) return -EFAULT; - if (user_sseu.flags || user_sseu.rsvd) + if (user_sseu.rsvd) return -EINVAL; - engine = intel_engine_lookup_user(i915, - user_sseu.engine_class, - user_sseu.engine_instance); - if (!engine) + if (user_sseu.flags & ~I915_SSEU_USE_ENGINE_MAP_INDEX) + return -EINVAL; + + ce = ctx_sseu_lookup_context(ctx, &user_sseu); + if (!ce) return -EINVAL; /* Only render engine supports RPCS configuration. */ - if (engine->class != RENDER_CLASS) + if (ce->owner->flags & I915_ENGINE_IS_VIRTUAL) { + if (ctx->engines[1]->class != RENDER_CLASS) + return -ENODEV; + } else if (ce->owner->class != RENDER_CLASS) { return -ENODEV; + } ret = user_to_context_sseu(i915, &user_sseu, &sseu); if (ret) return ret; - ret = i915_gem_context_reconfigure_sseu(ctx, engine, sseu); + ret = i915_gem_context_reconfigure_sseu(ce, sseu); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h index 778a18a6c08e..328e16001cfd 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.h +++ b/drivers/gpu/drm/i915/i915_gem_context.h @@ -225,6 +225,36 @@ struct i915_gem_context { struct list_head handles_list; }; +struct virtual_engine { + struct intel_engine_cs base; + + struct intel_context context; + struct kref kref; + + struct intel_engine_cs *bound; + + struct i915_request *request; + struct ve_node { + struct rb_node rb; + int prio; + } nodes[I915_NUM_ENGINES]; + + struct ve_bond { + struct intel_engine_cs *master; + unsigned int sibling_mask; + } *bonds; + unsigned int nbond; + + unsigned int count; + struct intel_engine_cs *siblings[0]; +}; + +static inline struct virtual_engine * +to_virtual_engine(struct intel_engine_cs *engine) +{ + return container_of(engine, struct virtual_engine, base); +} + static inline bool i915_gem_context_is_closed(const struct i915_gem_context *ctx) { return test_bit(CONTEXT_CLOSED, &ctx->flags); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 1f5e687f3b7f..c80624c01fa5 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -164,35 +164,6 @@ #define WA_TAIL_DWORDS 2 #define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS) -struct virtual_engine { - struct intel_engine_cs base; - - struct intel_context context; - struct kref kref; - - struct intel_engine_cs *bound; - - struct i915_request *request; - struct ve_node { - struct rb_node rb; - int prio; - } nodes[I915_NUM_ENGINES]; - - struct ve_bond { - struct intel_engine_cs *master; - unsigned int sibling_mask; - } *bonds; - unsigned int nbond; - - unsigned int count; - struct intel_engine_cs *siblings[0]; -}; - -static struct virtual_engine *to_virtual_engine(struct intel_engine_cs *engine) -{ - return container_of(engine, struct virtual_engine, base); -} - static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, struct intel_engine_cs *engine, struct intel_context *ce); diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 8d10683e8430..49651114e40a 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -1619,9 +1619,10 @@ struct drm_i915_gem_context_param_sseu { __u16 engine_instance; /* - * Unused for now. Must be cleared to zero. + * Set of flags controlling the ioctl behaviour. */ __u32 flags; +#define I915_SSEU_USE_ENGINE_MAP_INDEX (1 << 0) /* * Mask of slices to enable for the context. Valid values are a subset |