Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> writes: > If we remove some hardcoded assumptions about the preempt context having > a fixed id, reserved from use by normal user contexts, we may only > allocate the i915_gem_context when required. Then the subsequent > decisions on using preemption reduce to having the preempt context > available. > > Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> > Cc: Michal Winiarski <michal.winiarski@xxxxxxxxx> > Cc: Tvrtko Ursulin <tvrtko.ursulin@xxxxxxxxx> > Cc: Arkadiusz Hiler <arkadiusz.hiler@xxxxxxxxx> > Cc: Mika Kuoppala <mika.kuoppala@xxxxxxxxx> > Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@xxxxxxxxx> > --- > drivers/gpu/drm/i915/i915_gem_context.c | 29 ++++++++++++------------ > drivers/gpu/drm/i915/intel_engine_cs.c | 6 ++--- > drivers/gpu/drm/i915/intel_guc_submission.c | 24 +++++++++++--------- > drivers/gpu/drm/i915/intel_lrc.c | 17 +++++++++----- > drivers/gpu/drm/i915/intel_ringbuffer.h | 5 ++++ > drivers/gpu/drm/i915/selftests/mock_gem_device.c | 6 ----- > 6 files changed, 46 insertions(+), 41 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c > index 648e7536ff51..d69c8f1a4e78 100644 > --- a/drivers/gpu/drm/i915/i915_gem_context.c > +++ b/drivers/gpu/drm/i915/i915_gem_context.c > @@ -449,10 +449,14 @@ destroy_kernel_context(struct i915_gem_context **ctxp) > i915_gem_context_free(ctx); > } > > +static bool needs_preempt_context(struct drm_i915_private *i915) > +{ > + return HAS_LOGICAL_RING_PREEMPTION(i915); > +} > + > int i915_gem_contexts_init(struct drm_i915_private *dev_priv) > { > struct i915_gem_context *ctx; > - int err; > > GEM_BUG_ON(dev_priv->kernel_context); Please consider adding GEM_BUG_ON(dev_priv->preempt_context); here even tho the kernel_context should act as a master guard for init ordering errors. Even if no other than documenting that we expect a clean slate in this regard also. > > @@ -468,8 +472,7 @@ int i915_gem_contexts_init(struct drm_i915_private *dev_priv) > ctx = i915_gem_context_create_kernel(dev_priv, I915_PRIORITY_MIN); > if (IS_ERR(ctx)) { > DRM_ERROR("Failed to create default global context\n"); > - err = PTR_ERR(ctx); > - goto err; > + return PTR_ERR(ctx); > } > /* > * For easy recognisablity, we want the kernel context to be 0 and then > @@ -479,23 +482,18 @@ int i915_gem_contexts_init(struct drm_i915_private *dev_priv) > dev_priv->kernel_context = ctx; > > /* highest priority; preempting task */ > - ctx = i915_gem_context_create_kernel(dev_priv, INT_MAX); > - if (IS_ERR(ctx)) { > - DRM_ERROR("Failed to create default preempt context\n"); > - err = PTR_ERR(ctx); > - goto err_kernel_context; It seems this error path has been wrong all along. > + if (needs_preempt_context(dev_priv)) { > + ctx = i915_gem_context_create_kernel(dev_priv, INT_MAX); > + if (!IS_ERR(ctx)) > + dev_priv->preempt_context = ctx; > + else > + DRM_ERROR("Failed to create preempt context; disabling preemption\n"); > } > - dev_priv->preempt_context = ctx; > > DRM_DEBUG_DRIVER("%s context support initialized\n", > dev_priv->engine[RCS]->context_size ? "logical" : > "fake"); > return 0; > - > -err_kernel_context: > - destroy_kernel_context(&dev_priv->kernel_context); > -err: > - return err; > } > > void i915_gem_contexts_lost(struct drm_i915_private *dev_priv) > @@ -521,7 +519,8 @@ void i915_gem_contexts_fini(struct drm_i915_private *i915) > { > lockdep_assert_held(&i915->drm.struct_mutex); > > - destroy_kernel_context(&i915->preempt_context); > + if (i915->preempt_context) > + destroy_kernel_context(&i915->preempt_context); > destroy_kernel_context(&i915->kernel_context); > > /* Must free all deferred contexts (via flush_workqueue) first */ > diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c > index 7eebfbb95e89..bf634432c9c6 100644 > --- a/drivers/gpu/drm/i915/intel_engine_cs.c > +++ b/drivers/gpu/drm/i915/intel_engine_cs.c > @@ -631,7 +631,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine) > * Similarly the preempt context must always be available so that > * we can interrupt the engine at any time. > */ > - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) { > + if (engine->i915->preempt_context) { > ring = engine->context_pin(engine, > engine->i915->preempt_context); > if (IS_ERR(ring)) { > @@ -656,7 +656,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine) > err_breadcrumbs: > intel_engine_fini_breadcrumbs(engine); > err_unpin_preempt: > - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) > + if (engine->i915->preempt_context) > engine->context_unpin(engine, engine->i915->preempt_context); > err_unpin_kernel: > engine->context_unpin(engine, engine->i915->kernel_context); > @@ -686,7 +686,7 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) > if (engine->default_state) > i915_gem_object_put(engine->default_state); > > - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) > + if (engine->i915->preempt_context) > engine->context_unpin(engine, engine->i915->preempt_context); > engine->context_unpin(engine, engine->i915->kernel_context); > } > diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c > index 4ea65df05e02..b43b58cc599b 100644 > --- a/drivers/gpu/drm/i915/intel_guc_submission.c > +++ b/drivers/gpu/drm/i915/intel_guc_submission.c > @@ -688,7 +688,7 @@ static void guc_dequeue(struct intel_engine_cs *engine) > goto unlock; > > if (port_isset(port)) { > - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) { > + if (engine->i915->preempt_context) { > struct guc_preempt_work *preempt_work = > &engine->i915->guc.preempt_work[engine->id]; > > @@ -984,17 +984,19 @@ static int guc_clients_create(struct intel_guc *guc) > } > guc->execbuf_client = client; > > - client = guc_client_alloc(dev_priv, > - INTEL_INFO(dev_priv)->ring_mask, > - GUC_CLIENT_PRIORITY_KMD_HIGH, > - dev_priv->preempt_context); > - if (IS_ERR(client)) { > - DRM_ERROR("Failed to create GuC client for preemption!\n"); > - guc_client_free(guc->execbuf_client); > - guc->execbuf_client = NULL; > - return PTR_ERR(client); > + if (dev_priv->preempt_context) { > + client = guc_client_alloc(dev_priv, > + INTEL_INFO(dev_priv)->ring_mask, > + GUC_CLIENT_PRIORITY_KMD_HIGH, > + dev_priv->preempt_context); > + if (IS_ERR(client)) { > + DRM_ERROR("Failed to create GuC client for preemption!\n"); > + guc_client_free(guc->execbuf_client); > + guc->execbuf_client = NULL; > + return PTR_ERR(client); > + } > + guc->preempt_client = client; > } > - guc->preempt_client = client; > > return 0; > } > diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c > index 5390894001f0..221b62d72c72 100644 > --- a/drivers/gpu/drm/i915/intel_lrc.c > +++ b/drivers/gpu/drm/i915/intel_lrc.c > @@ -161,7 +161,6 @@ > #define EXECLISTS_REQUEST_SIZE 64 /* bytes */ > #define WA_TAIL_DWORDS 2 > #define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS) > -#define PREEMPT_ID 0x1 > > static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, > struct intel_engine_cs *engine); > @@ -448,7 +447,8 @@ static void inject_preempt_context(struct intel_engine_cs *engine) > &engine->i915->preempt_context->engine[engine->id]; > unsigned int n; > > - GEM_BUG_ON(engine->i915->preempt_context->hw_id != PREEMPT_ID); > + GEM_BUG_ON(engine->execlists.preempt_complete_status != > + upper_32_bits(ce->lrc_desc)); > GEM_BUG_ON(!IS_ALIGNED(ce->ring->size, WA_TAIL_BYTES)); > > memset(ce->ring->vaddr + ce->ring->tail, 0, WA_TAIL_BYTES); > @@ -528,7 +528,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) > if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_HWACK)) > goto unlock; > > - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915) && > + if (engine->i915->preempt_context && > rb_entry(rb, struct i915_priolist, node)->priority > > max(last->priotree.priority, 0)) { > /* > @@ -844,7 +844,7 @@ static void execlists_submission_tasklet(unsigned long data) > GEM_BUG_ON(status & GEN8_CTX_STATUS_IDLE_ACTIVE); > > if (status & GEN8_CTX_STATUS_COMPLETE && > - buf[2*head + 1] == PREEMPT_ID) { > + buf[2*head + 1] == execlists->preempt_complete_status) { > GEM_TRACE("%s preempt-idle\n", engine->name); > > execlists_cancel_port_requests(execlists); > @@ -1910,7 +1910,7 @@ static void execlists_set_default_submission(struct intel_engine_cs *engine) > engine->i915->caps.scheduler = > I915_SCHEDULER_CAP_ENABLED | > I915_SCHEDULER_CAP_PRIORITY; > - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) > + if (engine->i915->preempt_context) > engine->i915->caps.scheduler |= I915_SCHEDULER_CAP_PREEMPTION; > } > > @@ -1988,6 +1988,11 @@ static int logical_ring_init(struct intel_engine_cs *engine) > engine->execlists.elsp = > engine->i915->regs + i915_mmio_reg_offset(RING_ELSP(engine)); > > + engine->execlists.preempt_complete_status = ~0u; This is to ensure that we catch a rogue status? Atleast we will bug on of preempting with this status as the EXECLIST_ACTIVE_PREEMPT will be false. > + if (engine->i915->preempt_context) > + engine->execlists.preempt_complete_status = > + upper_32_bits(engine->i915->preempt_context->engine[engine->id].lrc_desc); We have not upgraded the descriptor yet, so just use preempt_context->hw_id; I would also like duplicate, from i915_gem_context.c, the assertion that hw_id needs to be <= INT_MAX but didn't find a good spot. -Mika > + > return 0; > > error: > @@ -2250,7 +2255,7 @@ populate_lr_context(struct i915_gem_context *ctx, > if (!engine->default_state) > regs[CTX_CONTEXT_CONTROL + 1] |= > _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); > - if (ctx->hw_id == PREEMPT_ID) > + if (ctx == ctx->i915->preempt_context) > regs[CTX_CONTEXT_CONTROL + 1] |= > _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | > CTX_CTRL_ENGINE_CTX_SAVE_INHIBIT); > diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h > index c5ff203e42d6..03be8995f415 100644 > --- a/drivers/gpu/drm/i915/intel_ringbuffer.h > +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h > @@ -279,6 +279,11 @@ struct intel_engine_execlists { > * @csb_use_mmio: access csb through mmio, instead of hwsp > */ > bool csb_use_mmio; > + > + /** > + * @preempt_complete_status: expected CSB upon completing preemption > + */ > + u32 preempt_complete_status; > }; > > #define INTEL_ENGINE_CS_MAX_NAME 8 > diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c > index 1bc61f3f76fc..3175db70cc6e 100644 > --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c > +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c > @@ -243,16 +243,10 @@ struct drm_i915_private *mock_gem_device(void) > if (!i915->kernel_context) > goto err_engine; > > - i915->preempt_context = mock_context(i915, NULL); > - if (!i915->preempt_context) > - goto err_kernel_context; > - > WARN_ON(i915_gemfs_init(i915)); > > return i915; > > -err_kernel_context: > - i915_gem_context_put(i915->kernel_context); > err_engine: > for_each_engine(engine, i915, id) > mock_engine_free(engine); > -- > 2.15.1 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/intel-gfx _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx