On 2018.05.17 22:26:32 +0100, Chris Wilson wrote: > To ease the frequent and ugly pointer dance of > &request->gem_context->engine[request->engine->id] during request > submission, store that pointer as request->hw_context. One major > advantage that we will exploit later is that this decouples the logical > context state from the engine itself. > > v2: Set mock_context->ops so we don't crash and burn in selftests. > Cleanups from Tvrtko. > > Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> > Cc: Tvrtko Ursulin <tvrtko.ursu...@intel.com> > --- > drivers/gpu/drm/i915/gvt/mmio_context.c | 6 +- > drivers/gpu/drm/i915/gvt/mmio_context.h | 2 +- > drivers/gpu/drm/i915/gvt/scheduler.c | 141 +++++++----------- > drivers/gpu/drm/i915/gvt/scheduler.h | 1 -
gvt change looks fine to me. Acked-by: Zhenyu Wang <zhen...@linux.intel.com> > drivers/gpu/drm/i915/i915_drv.h | 1 + > drivers/gpu/drm/i915/i915_gem.c | 12 +- > drivers/gpu/drm/i915/i915_gem_context.c | 17 ++- > drivers/gpu/drm/i915/i915_gem_context.h | 21 ++- > drivers/gpu/drm/i915/i915_gpu_error.c | 3 +- > drivers/gpu/drm/i915/i915_perf.c | 25 ++-- > drivers/gpu/drm/i915/i915_request.c | 34 ++--- > drivers/gpu/drm/i915/i915_request.h | 1 + > drivers/gpu/drm/i915/intel_engine_cs.c | 54 ++++--- > drivers/gpu/drm/i915/intel_guc_submission.c | 10 +- > drivers/gpu/drm/i915/intel_lrc.c | 125 +++++++++------- > drivers/gpu/drm/i915/intel_lrc.h | 7 - > drivers/gpu/drm/i915/intel_ringbuffer.c | 100 ++++++++----- > drivers/gpu/drm/i915/intel_ringbuffer.h | 9 +- > drivers/gpu/drm/i915/selftests/mock_context.c | 7 + > drivers/gpu/drm/i915/selftests/mock_engine.c | 41 +++-- > 20 files changed, 321 insertions(+), 296 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c > b/drivers/gpu/drm/i915/gvt/mmio_context.c > index 0f949554d118..708170e61625 100644 > --- a/drivers/gpu/drm/i915/gvt/mmio_context.c > +++ b/drivers/gpu/drm/i915/gvt/mmio_context.c > @@ -446,9 +446,9 @@ static void switch_mocs(struct intel_vgpu *pre, struct > intel_vgpu *next, > > #define CTX_CONTEXT_CONTROL_VAL 0x03 > > -bool is_inhibit_context(struct i915_gem_context *ctx, int ring_id) > +bool is_inhibit_context(struct intel_context *ce) > { > - u32 *reg_state = ctx->__engine[ring_id].lrc_reg_state; > + const u32 *reg_state = ce->lrc_reg_state; > u32 inhibit_mask = > _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); > > @@ -501,7 +501,7 @@ static void switch_mmio(struct intel_vgpu *pre, > * itself. > */ > if (mmio->in_context && > - !is_inhibit_context(s->shadow_ctx, ring_id)) > + > !is_inhibit_context(&s->shadow_ctx->__engine[ring_id])) > continue; > > if (mmio->mask) > diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.h > b/drivers/gpu/drm/i915/gvt/mmio_context.h > index 0439eb8057a8..5c3b9ff9f96a 100644 > --- a/drivers/gpu/drm/i915/gvt/mmio_context.h > +++ b/drivers/gpu/drm/i915/gvt/mmio_context.h > @@ -49,7 +49,7 @@ void intel_gvt_switch_mmio(struct intel_vgpu *pre, > > void intel_gvt_init_engine_mmio_context(struct intel_gvt *gvt); > > -bool is_inhibit_context(struct i915_gem_context *ctx, int ring_id); > +bool is_inhibit_context(struct intel_context *ce); > > int intel_vgpu_restore_inhibit_context(struct intel_vgpu *vgpu, > struct i915_request *req); > diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c > b/drivers/gpu/drm/i915/gvt/scheduler.c > index 17f9f8d7e148..e1760030dda1 100644 > --- a/drivers/gpu/drm/i915/gvt/scheduler.c > +++ b/drivers/gpu/drm/i915/gvt/scheduler.c > @@ -54,11 +54,8 @@ static void set_context_pdp_root_pointer( > > static void update_shadow_pdps(struct intel_vgpu_workload *workload) > { > - struct intel_vgpu *vgpu = workload->vgpu; > - int ring_id = workload->ring_id; > - struct i915_gem_context *shadow_ctx = vgpu->submission.shadow_ctx; > struct drm_i915_gem_object *ctx_obj = > - shadow_ctx->__engine[ring_id].state->obj; > + workload->req->hw_context->state->obj; > struct execlist_ring_context *shadow_ring_context; > struct page *page; > > @@ -128,9 +125,8 @@ static int populate_shadow_context(struct > intel_vgpu_workload *workload) > struct intel_vgpu *vgpu = workload->vgpu; > struct intel_gvt *gvt = vgpu->gvt; > int ring_id = workload->ring_id; > - struct i915_gem_context *shadow_ctx = vgpu->submission.shadow_ctx; > struct drm_i915_gem_object *ctx_obj = > - shadow_ctx->__engine[ring_id].state->obj; > + workload->req->hw_context->state->obj; > struct execlist_ring_context *shadow_ring_context; > struct page *page; > void *dst; > @@ -280,10 +276,8 @@ static int shadow_context_status_change(struct > notifier_block *nb, > return NOTIFY_OK; > } > > -static void shadow_context_descriptor_update(struct i915_gem_context *ctx, > - struct intel_engine_cs *engine) > +static void shadow_context_descriptor_update(struct intel_context *ce) > { > - struct intel_context *ce = to_intel_context(ctx, engine); > u64 desc = 0; > > desc = ce->lrc_desc; > @@ -292,7 +286,7 @@ static void shadow_context_descriptor_update(struct > i915_gem_context *ctx, > * like GEN8_CTX_* cached in desc_template > */ > desc &= U64_MAX << 12; > - desc |= ctx->desc_template & ((1ULL << 12) - 1); > + desc |= ce->gem_context->desc_template & ((1ULL << 12) - 1); > > ce->lrc_desc = desc; > } > @@ -300,12 +294,11 @@ static void shadow_context_descriptor_update(struct > i915_gem_context *ctx, > static int copy_workload_to_ring_buffer(struct intel_vgpu_workload *workload) > { > struct intel_vgpu *vgpu = workload->vgpu; > + struct i915_request *req = workload->req; > void *shadow_ring_buffer_va; > u32 *cs; > - struct i915_request *req = workload->req; > > - if (IS_KABYLAKE(req->i915) && > - is_inhibit_context(req->gem_context, req->engine->id)) > + if (IS_KABYLAKE(req->i915) && is_inhibit_context(req->hw_context)) > intel_vgpu_restore_inhibit_context(vgpu, req); > > /* allocate shadow ring buffer */ > @@ -353,60 +346,56 @@ int intel_gvt_scan_and_shadow_workload(struct > intel_vgpu_workload *workload) > struct intel_vgpu_submission *s = &vgpu->submission; > struct i915_gem_context *shadow_ctx = s->shadow_ctx; > struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; > - int ring_id = workload->ring_id; > - struct intel_engine_cs *engine = dev_priv->engine[ring_id]; > - struct intel_ring *ring; > + struct intel_engine_cs *engine = dev_priv->engine[workload->ring_id]; > + struct intel_context *ce; > int ret; > > lockdep_assert_held(&dev_priv->drm.struct_mutex); > > - if (workload->shadowed) > + if (workload->req) > return 0; > > + /* pin shadow context by gvt even the shadow context will be pinned > + * when i915 alloc request. That is because gvt will update the guest > + * context from shadow context when workload is completed, and at that > + * moment, i915 may already unpined the shadow context to make the > + * shadow_ctx pages invalid. So gvt need to pin itself. After update > + * the guest context, gvt can unpin the shadow_ctx safely. > + */ > + ce = intel_context_pin(shadow_ctx, engine); > + if (IS_ERR(ce)) { > + gvt_vgpu_err("fail to pin shadow context\n"); > + return PTR_ERR(ce); > + } > + > shadow_ctx->desc_template &= ~(0x3 << GEN8_CTX_ADDRESSING_MODE_SHIFT); > shadow_ctx->desc_template |= workload->ctx_desc.addressing_mode << > GEN8_CTX_ADDRESSING_MODE_SHIFT; > > - if (!test_and_set_bit(ring_id, s->shadow_ctx_desc_updated)) > - shadow_context_descriptor_update(shadow_ctx, > - dev_priv->engine[ring_id]); > + if (!test_and_set_bit(workload->ring_id, s->shadow_ctx_desc_updated)) > + shadow_context_descriptor_update(ce); > > ret = intel_gvt_scan_and_shadow_ringbuffer(workload); > if (ret) > - goto err_scan; > + goto err_unpin; > > if ((workload->ring_id == RCS) && > (workload->wa_ctx.indirect_ctx.size != 0)) { > ret = intel_gvt_scan_and_shadow_wa_ctx(&workload->wa_ctx); > if (ret) > - goto err_scan; > - } > - > - /* pin shadow context by gvt even the shadow context will be pinned > - * when i915 alloc request. That is because gvt will update the guest > - * context from shadow context when workload is completed, and at that > - * moment, i915 may already unpined the shadow context to make the > - * shadow_ctx pages invalid. So gvt need to pin itself. After update > - * the guest context, gvt can unpin the shadow_ctx safely. > - */ > - ring = intel_context_pin(shadow_ctx, engine); > - if (IS_ERR(ring)) { > - ret = PTR_ERR(ring); > - gvt_vgpu_err("fail to pin shadow context\n"); > - goto err_shadow; > + goto err_shadow; > } > > ret = populate_shadow_context(workload); > if (ret) > - goto err_unpin; > - workload->shadowed = true; > + goto err_shadow; > + > return 0; > > -err_unpin: > - intel_context_unpin(shadow_ctx, engine); > err_shadow: > release_shadow_wa_ctx(&workload->wa_ctx); > -err_scan: > +err_unpin: > + intel_context_unpin(ce); > return ret; > } > > @@ -414,7 +403,6 @@ static int intel_gvt_generate_request(struct > intel_vgpu_workload *workload) > { > int ring_id = workload->ring_id; > struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; > - struct intel_engine_cs *engine = dev_priv->engine[ring_id]; > struct i915_request *rq; > struct intel_vgpu *vgpu = workload->vgpu; > struct intel_vgpu_submission *s = &vgpu->submission; > @@ -437,7 +425,6 @@ static int intel_gvt_generate_request(struct > intel_vgpu_workload *workload) > return 0; > > err_unpin: > - intel_context_unpin(shadow_ctx, engine); > release_shadow_wa_ctx(&workload->wa_ctx); > return ret; > } > @@ -517,21 +504,13 @@ static int prepare_shadow_batch_buffer(struct > intel_vgpu_workload *workload) > return ret; > } > > -static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) > +static void update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) > { > - struct intel_vgpu_workload *workload = container_of(wa_ctx, > - struct intel_vgpu_workload, > - wa_ctx); > - int ring_id = workload->ring_id; > - struct intel_vgpu_submission *s = &workload->vgpu->submission; > - struct i915_gem_context *shadow_ctx = s->shadow_ctx; > - struct drm_i915_gem_object *ctx_obj = > - shadow_ctx->__engine[ring_id].state->obj; > - struct execlist_ring_context *shadow_ring_context; > - struct page *page; > - > - page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); > - shadow_ring_context = kmap_atomic(page); > + struct intel_vgpu_workload *workload = > + container_of(wa_ctx, struct intel_vgpu_workload, wa_ctx); > + struct i915_request *rq = workload->req; > + struct execlist_ring_context *shadow_ring_context = > + (struct execlist_ring_context *)rq->hw_context->lrc_reg_state; > > shadow_ring_context->bb_per_ctx_ptr.val = > (shadow_ring_context->bb_per_ctx_ptr.val & > @@ -539,9 +518,6 @@ static int update_wa_ctx_2_shadow_ctx(struct > intel_shadow_wa_ctx *wa_ctx) > shadow_ring_context->rcs_indirect_ctx.val = > (shadow_ring_context->rcs_indirect_ctx.val & > (~INDIRECT_CTX_ADDR_MASK)) | wa_ctx->indirect_ctx.shadow_gma; > - > - kunmap_atomic(shadow_ring_context); > - return 0; > } > > static int prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) > @@ -670,12 +646,9 @@ static int prepare_workload(struct intel_vgpu_workload > *workload) > static int dispatch_workload(struct intel_vgpu_workload *workload) > { > struct intel_vgpu *vgpu = workload->vgpu; > - struct intel_vgpu_submission *s = &vgpu->submission; > - struct i915_gem_context *shadow_ctx = s->shadow_ctx; > struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; > int ring_id = workload->ring_id; > - struct intel_engine_cs *engine = dev_priv->engine[ring_id]; > - int ret = 0; > + int ret; > > gvt_dbg_sched("ring id %d prepare to dispatch workload %p\n", > ring_id, workload); > @@ -687,10 +660,6 @@ static int dispatch_workload(struct intel_vgpu_workload > *workload) > goto out; > > ret = prepare_workload(workload); > - if (ret) { > - intel_context_unpin(shadow_ctx, engine); > - goto out; > - } > > out: > if (ret) > @@ -765,27 +734,23 @@ static struct intel_vgpu_workload *pick_next_workload( > > static void update_guest_context(struct intel_vgpu_workload *workload) > { > + struct i915_request *rq = workload->req; > struct intel_vgpu *vgpu = workload->vgpu; > struct intel_gvt *gvt = vgpu->gvt; > - struct intel_vgpu_submission *s = &vgpu->submission; > - struct i915_gem_context *shadow_ctx = s->shadow_ctx; > - int ring_id = workload->ring_id; > - struct drm_i915_gem_object *ctx_obj = > - shadow_ctx->__engine[ring_id].state->obj; > + struct drm_i915_gem_object *ctx_obj = rq->hw_context->state->obj; > struct execlist_ring_context *shadow_ring_context; > struct page *page; > void *src; > unsigned long context_gpa, context_page_num; > int i; > > - gvt_dbg_sched("ring id %d workload lrca %x\n", ring_id, > - workload->ctx_desc.lrca); > - > - context_page_num = gvt->dev_priv->engine[ring_id]->context_size; > + gvt_dbg_sched("ring id %d workload lrca %x\n", rq->engine->id, > + workload->ctx_desc.lrca); > > + context_page_num = rq->engine->context_size; > context_page_num = context_page_num >> PAGE_SHIFT; > > - if (IS_BROADWELL(gvt->dev_priv) && ring_id == RCS) > + if (IS_BROADWELL(gvt->dev_priv) && rq->engine->id == RCS) > context_page_num = 19; > > i = 2; > @@ -858,6 +823,7 @@ static void complete_current_workload(struct intel_gvt > *gvt, int ring_id) > scheduler->current_workload[ring_id]; > struct intel_vgpu *vgpu = workload->vgpu; > struct intel_vgpu_submission *s = &vgpu->submission; > + struct i915_request *rq; > int event; > > mutex_lock(&gvt->lock); > @@ -866,11 +832,8 @@ static void complete_current_workload(struct intel_gvt > *gvt, int ring_id) > * switch to make sure request is completed. > * For the workload w/o request, directly complete the workload. > */ > - if (workload->req) { > - struct drm_i915_private *dev_priv = > - workload->vgpu->gvt->dev_priv; > - struct intel_engine_cs *engine = > - dev_priv->engine[workload->ring_id]; > + rq = fetch_and_zero(&workload->req); > + if (rq) { > wait_event(workload->shadow_ctx_status_wq, > !atomic_read(&workload->shadow_ctx_active)); > > @@ -886,8 +849,6 @@ static void complete_current_workload(struct intel_gvt > *gvt, int ring_id) > workload->status = 0; > } > > - i915_request_put(fetch_and_zero(&workload->req)); > - > if (!workload->status && !(vgpu->resetting_eng & > ENGINE_MASK(ring_id))) { > update_guest_context(workload); > @@ -896,10 +857,13 @@ static void complete_current_workload(struct intel_gvt > *gvt, int ring_id) > INTEL_GVT_EVENT_MAX) > intel_vgpu_trigger_virtual_event(vgpu, event); > } > - mutex_lock(&dev_priv->drm.struct_mutex); > + > /* unpin shadow ctx as the shadow_ctx update is done */ > - intel_context_unpin(s->shadow_ctx, engine); > - mutex_unlock(&dev_priv->drm.struct_mutex); > + mutex_lock(&rq->i915->drm.struct_mutex); > + intel_context_unpin(rq->hw_context); > + mutex_unlock(&rq->i915->drm.struct_mutex); > + > + i915_request_put(rq); > } > > gvt_dbg_sched("ring id %d complete workload %p status %d\n", > @@ -1270,7 +1234,6 @@ alloc_workload(struct intel_vgpu *vgpu) > atomic_set(&workload->shadow_ctx_active, 0); > > workload->status = -EINPROGRESS; > - workload->shadowed = false; > workload->vgpu = vgpu; > > return workload; > diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h > b/drivers/gpu/drm/i915/gvt/scheduler.h > index 6c644782193e..21eddab4a9cd 100644 > --- a/drivers/gpu/drm/i915/gvt/scheduler.h > +++ b/drivers/gpu/drm/i915/gvt/scheduler.h > @@ -83,7 +83,6 @@ struct intel_vgpu_workload { > struct i915_request *req; > /* if this workload has been dispatched to i915? */ > bool dispatched; > - bool shadowed; > int status; > > struct intel_vgpu_mm *shadow_mm; > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 34c125e2d90c..e33c380b43e3 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -1950,6 +1950,7 @@ struct drm_i915_private { > */ > struct i915_perf_stream *exclusive_stream; > > + struct intel_context *pinned_ctx; > u32 specific_ctx_id; > > struct hrtimer poll_check_timer; > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c > index a20f8db5729d..03874b50ada9 100644 > --- a/drivers/gpu/drm/i915/i915_gem.c > +++ b/drivers/gpu/drm/i915/i915_gem.c > @@ -3181,14 +3181,14 @@ void i915_gem_reset(struct drm_i915_private *dev_priv, > i915_retire_requests(dev_priv); > > for_each_engine(engine, dev_priv, id) { > - struct i915_gem_context *ctx; > + struct intel_context *ce; > > i915_gem_reset_engine(engine, > engine->hangcheck.active_request, > stalled_mask & ENGINE_MASK(id)); > - ctx = fetch_and_zero(&engine->last_retired_context); > - if (ctx) > - intel_context_unpin(ctx, engine); > + ce = fetch_and_zero(&engine->last_retired_context); > + if (ce) > + intel_context_unpin(ce); > > /* > * Ostensibily, we always want a context loaded for powersaving, > @@ -4897,13 +4897,13 @@ void __i915_gem_object_release_unless_active(struct > drm_i915_gem_object *obj) > > static void assert_kernel_context_is_current(struct drm_i915_private *i915) > { > - struct i915_gem_context *kernel_context = i915->kernel_context; > + struct i915_gem_context *kctx = i915->kernel_context; > struct intel_engine_cs *engine; > enum intel_engine_id id; > > for_each_engine(engine, i915, id) { > > GEM_BUG_ON(__i915_gem_active_peek(&engine->timeline.last_request)); > - GEM_BUG_ON(engine->last_retired_context != kernel_context); > + GEM_BUG_ON(engine->last_retired_context->gem_context != kctx); > } > } > > diff --git a/drivers/gpu/drm/i915/i915_gem_context.c > b/drivers/gpu/drm/i915/i915_gem_context.c > index 9e70f4dfa703..b69b18ef8120 100644 > --- a/drivers/gpu/drm/i915/i915_gem_context.c > +++ b/drivers/gpu/drm/i915/i915_gem_context.c > @@ -127,14 +127,8 @@ static void i915_gem_context_free(struct > i915_gem_context *ctx) > for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++) { > struct intel_context *ce = &ctx->__engine[n]; > > - if (!ce->state) > - continue; > - > - WARN_ON(ce->pin_count); > - if (ce->ring) > - intel_ring_free(ce->ring); > - > - __i915_gem_object_release_unless_active(ce->state->obj); > + if (ce->ops) > + ce->ops->destroy(ce); > } > > kfree(ctx->name); > @@ -266,6 +260,7 @@ __create_hw_context(struct drm_i915_private *dev_priv, > struct drm_i915_file_private *file_priv) > { > struct i915_gem_context *ctx; > + unsigned int n; > int ret; > > ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); > @@ -283,6 +278,12 @@ __create_hw_context(struct drm_i915_private *dev_priv, > ctx->i915 = dev_priv; > ctx->sched.priority = I915_PRIORITY_NORMAL; > > + for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++) { > + struct intel_context *ce = &ctx->__engine[n]; > + > + ce->gem_context = ctx; > + } > + > INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL); > INIT_LIST_HEAD(&ctx->handles_list); > > diff --git a/drivers/gpu/drm/i915/i915_gem_context.h > b/drivers/gpu/drm/i915/i915_gem_context.h > index ace3b129c189..749a4ff566f5 100644 > --- a/drivers/gpu/drm/i915/i915_gem_context.h > +++ b/drivers/gpu/drm/i915/i915_gem_context.h > @@ -45,6 +45,11 @@ struct intel_ring; > > #define DEFAULT_CONTEXT_HANDLE 0 > > +struct intel_context_ops { > + void (*unpin)(struct intel_context *ce); > + void (*destroy)(struct intel_context *ce); > +}; > + > /** > * struct i915_gem_context - client state > * > @@ -144,11 +149,14 @@ struct i915_gem_context { > > /** engine: per-engine logical HW state */ > struct intel_context { > + struct i915_gem_context *gem_context; > struct i915_vma *state; > struct intel_ring *ring; > u32 *lrc_reg_state; > u64 lrc_desc; > int pin_count; > + > + const struct intel_context_ops *ops; > } __engine[I915_NUM_ENGINES]; > > /** ring_size: size for allocating the per-engine ring buffer */ > @@ -263,25 +271,22 @@ to_intel_context(struct i915_gem_context *ctx, > return &ctx->__engine[engine->id]; > } > > -static inline struct intel_ring * > +static inline struct intel_context * > intel_context_pin(struct i915_gem_context *ctx, struct intel_engine_cs > *engine) > { > return engine->context_pin(engine, ctx); > } > > -static inline void __intel_context_pin(struct i915_gem_context *ctx, > - const struct intel_engine_cs *engine) > +static inline void __intel_context_pin(struct intel_context *ce) > { > - struct intel_context *ce = to_intel_context(ctx, engine); > - > GEM_BUG_ON(!ce->pin_count); > ce->pin_count++; > } > > -static inline void intel_context_unpin(struct i915_gem_context *ctx, > - struct intel_engine_cs *engine) > +static inline void intel_context_unpin(struct intel_context *ce) > { > - engine->context_unpin(engine, ctx); > + GEM_BUG_ON(!ce->ops); > + ce->ops->unpin(ce); > } > > /* i915_gem_context.c */ > diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c > b/drivers/gpu/drm/i915/i915_gpu_error.c > index 7cc7d3bc731b..145823f0b48e 100644 > --- a/drivers/gpu/drm/i915/i915_gpu_error.c > +++ b/drivers/gpu/drm/i915/i915_gpu_error.c > @@ -1485,8 +1485,7 @@ static void gem_record_rings(struct i915_gpu_state > *error) > > ee->ctx = > i915_error_object_create(i915, > - to_intel_context(ctx, > - > engine)->state); > + > request->hw_context->state); > > error->simulated |= > i915_gem_context_no_error_capture(ctx); > diff --git a/drivers/gpu/drm/i915/i915_perf.c > b/drivers/gpu/drm/i915/i915_perf.c > index 019bd2d073ad..4f0eb84b3c00 100644 > --- a/drivers/gpu/drm/i915/i915_perf.c > +++ b/drivers/gpu/drm/i915/i915_perf.c > @@ -1221,7 +1221,7 @@ static int oa_get_render_ctx_id(struct i915_perf_stream > *stream) > dev_priv->perf.oa.specific_ctx_id = stream->ctx->hw_id; > } else { > struct intel_engine_cs *engine = dev_priv->engine[RCS]; > - struct intel_ring *ring; > + struct intel_context *ce; > int ret; > > ret = i915_mutex_lock_interruptible(&dev_priv->drm); > @@ -1234,19 +1234,19 @@ static int oa_get_render_ctx_id(struct > i915_perf_stream *stream) > * > * NB: implied RCS engine... > */ > - ring = intel_context_pin(stream->ctx, engine); > + ce = intel_context_pin(stream->ctx, engine); > mutex_unlock(&dev_priv->drm.struct_mutex); > - if (IS_ERR(ring)) > - return PTR_ERR(ring); > + if (IS_ERR(ce)) > + return PTR_ERR(ce); > > + dev_priv->perf.oa.pinned_ctx = ce; > > /* > * Explicitly track the ID (instead of calling > * i915_ggtt_offset() on the fly) considering the difference > * with gen8+ and execlists > */ > - dev_priv->perf.oa.specific_ctx_id = > - i915_ggtt_offset(to_intel_context(stream->ctx, > engine)->state); > + dev_priv->perf.oa.specific_ctx_id = i915_ggtt_offset(ce->state); > } > > return 0; > @@ -1262,17 +1262,14 @@ static int oa_get_render_ctx_id(struct > i915_perf_stream *stream) > static void oa_put_render_ctx_id(struct i915_perf_stream *stream) > { > struct drm_i915_private *dev_priv = stream->dev_priv; > + struct intel_context *ce; > > - if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { > - dev_priv->perf.oa.specific_ctx_id = INVALID_CTX_ID; > - } else { > - struct intel_engine_cs *engine = dev_priv->engine[RCS]; > + dev_priv->perf.oa.specific_ctx_id = INVALID_CTX_ID; > > + ce = fetch_and_zero(&dev_priv->perf.oa.pinned_ctx); > + if (ce) { > mutex_lock(&dev_priv->drm.struct_mutex); > - > - dev_priv->perf.oa.specific_ctx_id = INVALID_CTX_ID; > - intel_context_unpin(stream->ctx, engine); > - > + intel_context_unpin(ce); > mutex_unlock(&dev_priv->drm.struct_mutex); > } > } > diff --git a/drivers/gpu/drm/i915/i915_request.c > b/drivers/gpu/drm/i915/i915_request.c > index fe8810a6a339..fc499bcbd105 100644 > --- a/drivers/gpu/drm/i915/i915_request.c > +++ b/drivers/gpu/drm/i915/i915_request.c > @@ -383,8 +383,8 @@ static void __retire_engine_request(struct > intel_engine_cs *engine, > * the subsequent request. > */ > if (engine->last_retired_context) > - intel_context_unpin(engine->last_retired_context, engine); > - engine->last_retired_context = rq->gem_context; > + intel_context_unpin(engine->last_retired_context); > + engine->last_retired_context = rq->hw_context; > } > > static void __retire_engine_upto(struct intel_engine_cs *engine, > @@ -456,7 +456,7 @@ static void i915_request_retire(struct i915_request > *request) > > /* Retirement decays the ban score as it is a sign of ctx progress */ > atomic_dec_if_positive(&request->gem_context->ban_score); > - intel_context_unpin(request->gem_context, request->engine); > + intel_context_unpin(request->hw_context); > > __retire_engine_upto(request->engine, request); > > @@ -657,7 +657,7 @@ i915_request_alloc(struct intel_engine_cs *engine, struct > i915_gem_context *ctx) > { > struct drm_i915_private *i915 = engine->i915; > struct i915_request *rq; > - struct intel_ring *ring; > + struct intel_context *ce; > int ret; > > lockdep_assert_held(&i915->drm.struct_mutex); > @@ -681,22 +681,21 @@ i915_request_alloc(struct intel_engine_cs *engine, > struct i915_gem_context *ctx) > * GGTT space, so do this first before we reserve a seqno for > * ourselves. > */ > - ring = intel_context_pin(ctx, engine); > - if (IS_ERR(ring)) > - return ERR_CAST(ring); > - GEM_BUG_ON(!ring); > + ce = intel_context_pin(ctx, engine); > + if (IS_ERR(ce)) > + return ERR_CAST(ce); > > ret = reserve_gt(i915); > if (ret) > goto err_unpin; > > - ret = intel_ring_wait_for_space(ring, MIN_SPACE_FOR_ADD_REQUEST); > + ret = intel_ring_wait_for_space(ce->ring, MIN_SPACE_FOR_ADD_REQUEST); > if (ret) > goto err_unreserve; > > /* Move our oldest request to the slab-cache (if not in use!) */ > - rq = list_first_entry(&ring->request_list, typeof(*rq), ring_link); > - if (!list_is_last(&rq->ring_link, &ring->request_list) && > + rq = list_first_entry(&ce->ring->request_list, typeof(*rq), ring_link); > + if (!list_is_last(&rq->ring_link, &ce->ring->request_list) && > i915_request_completed(rq)) > i915_request_retire(rq); > > @@ -761,8 +760,9 @@ i915_request_alloc(struct intel_engine_cs *engine, struct > i915_gem_context *ctx) > rq->i915 = i915; > rq->engine = engine; > rq->gem_context = ctx; > - rq->ring = ring; > - rq->timeline = ring->timeline; > + rq->hw_context = ce; > + rq->ring = ce->ring; > + rq->timeline = ce->ring->timeline; > GEM_BUG_ON(rq->timeline == &engine->timeline); > > spin_lock_init(&rq->lock); > @@ -814,14 +814,14 @@ i915_request_alloc(struct intel_engine_cs *engine, > struct i915_gem_context *ctx) > goto err_unwind; > > /* Keep a second pin for the dual retirement along engine and ring */ > - __intel_context_pin(rq->gem_context, engine); > + __intel_context_pin(ce); > > /* Check that we didn't interrupt ourselves with a new request */ > GEM_BUG_ON(rq->timeline->seqno != rq->fence.seqno); > return rq; > > err_unwind: > - rq->ring->emit = rq->head; > + ce->ring->emit = rq->head; > > /* Make sure we didn't add ourselves to external state before freeing */ > GEM_BUG_ON(!list_empty(&rq->active_list)); > @@ -832,7 +832,7 @@ i915_request_alloc(struct intel_engine_cs *engine, struct > i915_gem_context *ctx) > err_unreserve: > unreserve_gt(i915); > err_unpin: > - intel_context_unpin(ctx, engine); > + intel_context_unpin(ce); > return ERR_PTR(ret); > } > > @@ -1018,8 +1018,8 @@ i915_request_await_object(struct i915_request *to, > void __i915_request_add(struct i915_request *request, bool flush_caches) > { > struct intel_engine_cs *engine = request->engine; > - struct intel_ring *ring = request->ring; > struct i915_timeline *timeline = request->timeline; > + struct intel_ring *ring = request->ring; > struct i915_request *prev; > u32 *cs; > int err; > diff --git a/drivers/gpu/drm/i915/i915_request.h > b/drivers/gpu/drm/i915/i915_request.h > index dddecd9ffd0c..1bbbb7a9fa03 100644 > --- a/drivers/gpu/drm/i915/i915_request.h > +++ b/drivers/gpu/drm/i915/i915_request.h > @@ -95,6 +95,7 @@ struct i915_request { > */ > struct i915_gem_context *gem_context; > struct intel_engine_cs *engine; > + struct intel_context *hw_context; > struct intel_ring *ring; > struct i915_timeline *timeline; > struct intel_signal_node signaling; > diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c > b/drivers/gpu/drm/i915/intel_engine_cs.c > index 9e618aab6568..26f9f8aab949 100644 > --- a/drivers/gpu/drm/i915/intel_engine_cs.c > +++ b/drivers/gpu/drm/i915/intel_engine_cs.c > @@ -645,6 +645,12 @@ static int init_phys_status_page(struct intel_engine_cs > *engine) > return 0; > } > > +static void __intel_context_unpin(struct i915_gem_context *ctx, > + struct intel_engine_cs *engine) > +{ > + intel_context_unpin(to_intel_context(ctx, engine)); > +} > + > /** > * intel_engines_init_common - initialize cengine state which might require > hw access > * @engine: Engine to initialize. > @@ -658,7 +664,8 @@ static int init_phys_status_page(struct intel_engine_cs > *engine) > */ > int intel_engine_init_common(struct intel_engine_cs *engine) > { > - struct intel_ring *ring; > + struct drm_i915_private *i915 = engine->i915; > + struct intel_context *ce; > int ret; > > engine->set_default_submission(engine); > @@ -670,18 +677,18 @@ int intel_engine_init_common(struct intel_engine_cs > *engine) > * be available. To avoid this we always pin the default > * context. > */ > - ring = intel_context_pin(engine->i915->kernel_context, engine); > - if (IS_ERR(ring)) > - return PTR_ERR(ring); > + ce = intel_context_pin(i915->kernel_context, engine); > + if (IS_ERR(ce)) > + return PTR_ERR(ce); > > /* > * Similarly the preempt context must always be available so that > * we can interrupt the engine at any time. > */ > - if (engine->i915->preempt_context) { > - ring = intel_context_pin(engine->i915->preempt_context, engine); > - if (IS_ERR(ring)) { > - ret = PTR_ERR(ring); > + if (i915->preempt_context) { > + ce = intel_context_pin(i915->preempt_context, engine); > + if (IS_ERR(ce)) { > + ret = PTR_ERR(ce); > goto err_unpin_kernel; > } > } > @@ -690,7 +697,7 @@ int intel_engine_init_common(struct intel_engine_cs > *engine) > if (ret) > goto err_unpin_preempt; > > - if (HWS_NEEDS_PHYSICAL(engine->i915)) > + if (HWS_NEEDS_PHYSICAL(i915)) > ret = init_phys_status_page(engine); > else > ret = init_status_page(engine); > @@ -702,10 +709,11 @@ int intel_engine_init_common(struct intel_engine_cs > *engine) > err_breadcrumbs: > intel_engine_fini_breadcrumbs(engine); > err_unpin_preempt: > - if (engine->i915->preempt_context) > - intel_context_unpin(engine->i915->preempt_context, engine); > + if (i915->preempt_context) > + __intel_context_unpin(i915->preempt_context, engine); > + > err_unpin_kernel: > - intel_context_unpin(engine->i915->kernel_context, engine); > + __intel_context_unpin(i915->kernel_context, engine); > return ret; > } > > @@ -718,6 +726,8 @@ int intel_engine_init_common(struct intel_engine_cs > *engine) > */ > void intel_engine_cleanup_common(struct intel_engine_cs *engine) > { > + struct drm_i915_private *i915 = engine->i915; > + > intel_engine_cleanup_scratch(engine); > > if (HWS_NEEDS_PHYSICAL(engine->i915)) > @@ -732,9 +742,9 @@ void intel_engine_cleanup_common(struct intel_engine_cs > *engine) > if (engine->default_state) > i915_gem_object_put(engine->default_state); > > - if (engine->i915->preempt_context) > - intel_context_unpin(engine->i915->preempt_context, engine); > - intel_context_unpin(engine->i915->kernel_context, engine); > + if (i915->preempt_context) > + __intel_context_unpin(i915->preempt_context, engine); > + __intel_context_unpin(i915->kernel_context, engine); > > i915_timeline_fini(&engine->timeline); > } > @@ -1007,8 +1017,8 @@ bool intel_engines_are_idle(struct drm_i915_private > *dev_priv) > */ > bool intel_engine_has_kernel_context(const struct intel_engine_cs *engine) > { > - const struct i915_gem_context * const kernel_context = > - engine->i915->kernel_context; > + const struct intel_context *kernel_context = > + to_intel_context(engine->i915->kernel_context, engine); > struct i915_request *rq; > > lockdep_assert_held(&engine->i915->drm.struct_mutex); > @@ -1020,7 +1030,7 @@ bool intel_engine_has_kernel_context(const struct > intel_engine_cs *engine) > */ > rq = __i915_gem_active_peek(&engine->timeline.last_request); > if (rq) > - return rq->gem_context == kernel_context; > + return rq->hw_context == kernel_context; > else > return engine->last_retired_context == kernel_context; > } > @@ -1107,16 +1117,16 @@ void intel_engines_unpark(struct drm_i915_private > *i915) > */ > void intel_engine_lost_context(struct intel_engine_cs *engine) > { > - struct i915_gem_context *ctx; > + struct intel_context *ce; > > lockdep_assert_held(&engine->i915->drm.struct_mutex); > > engine->legacy_active_context = NULL; > engine->legacy_active_ppgtt = NULL; > > - ctx = fetch_and_zero(&engine->last_retired_context); > - if (ctx) > - intel_context_unpin(ctx, engine); > + ce = fetch_and_zero(&engine->last_retired_context); > + if (ce) > + intel_context_unpin(ce); > } > > bool intel_engine_can_store_dword(struct intel_engine_cs *engine) > diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c > b/drivers/gpu/drm/i915/intel_guc_submission.c > index a432a193f3c4..133367a17863 100644 > --- a/drivers/gpu/drm/i915/intel_guc_submission.c > +++ b/drivers/gpu/drm/i915/intel_guc_submission.c > @@ -513,9 +513,7 @@ static void guc_add_request(struct intel_guc *guc, struct > i915_request *rq) > { > struct intel_guc_client *client = guc->execbuf_client; > struct intel_engine_cs *engine = rq->engine; > - u32 ctx_desc = > - lower_32_bits(intel_lr_context_descriptor(rq->gem_context, > - engine)); > + u32 ctx_desc = lower_32_bits(rq->hw_context->lrc_desc); > u32 ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64); > > spin_lock(&client->wq_lock); > @@ -553,8 +551,8 @@ static void inject_preempt_context(struct work_struct > *work) > preempt_work[engine->id]); > struct intel_guc_client *client = guc->preempt_client; > struct guc_stage_desc *stage_desc = __get_stage_desc(client); > - u32 ctx_desc = lower_32_bits(intel_lr_context_descriptor(client->owner, > - engine)); > + u32 ctx_desc = lower_32_bits(to_intel_context(client->owner, > + engine)->lrc_desc); > u32 data[7]; > > /* > @@ -726,7 +724,7 @@ static bool __guc_dequeue(struct intel_engine_cs *engine) > struct i915_request *rq, *rn; > > list_for_each_entry_safe(rq, rn, &p->requests, sched.link) { > - if (last && rq->gem_context != last->gem_context) { > + if (last && rq->hw_context != last->hw_context) { > if (port == last_port) { > __list_del_many(&p->requests, > &rq->sched.link); > diff --git a/drivers/gpu/drm/i915/intel_lrc.c > b/drivers/gpu/drm/i915/intel_lrc.c > index 813f114a7c93..89a3a31721da 100644 > --- a/drivers/gpu/drm/i915/intel_lrc.c > +++ b/drivers/gpu/drm/i915/intel_lrc.c > @@ -164,7 +164,8 @@ > #define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS) > > static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, > - struct intel_engine_cs *engine); > + struct intel_engine_cs *engine, > + struct intel_context *ce); > static void execlists_init_reg_state(u32 *reg_state, > struct i915_gem_context *ctx, > struct intel_engine_cs *engine, > @@ -189,12 +190,7 @@ static inline bool need_preempt(const struct > intel_engine_cs *engine, > !i915_request_completed(last)); > } > > -/** > - * intel_lr_context_descriptor_update() - calculate & cache the descriptor > - * descriptor for a pinned context > - * @ctx: Context to work on > - * @engine: Engine the descriptor will be used with > - * > +/* > * The context descriptor encodes various attributes of a context, > * including its GTT address and some flags. Because it's fairly > * expensive to calculate, we'll just do it once and cache the result, > @@ -222,9 +218,9 @@ static inline bool need_preempt(const struct > intel_engine_cs *engine, > */ > static void > intel_lr_context_descriptor_update(struct i915_gem_context *ctx, > - struct intel_engine_cs *engine) > + struct intel_engine_cs *engine, > + struct intel_context *ce) > { > - struct intel_context *ce = to_intel_context(ctx, engine); > u64 desc; > > BUILD_BUG_ON(MAX_CONTEXT_HW_ID > (BIT(GEN8_CTX_ID_WIDTH))); > @@ -418,8 +414,7 @@ execlists_update_context_pdps(struct i915_hw_ppgtt > *ppgtt, u32 *reg_state) > > static u64 execlists_update_context(struct i915_request *rq) > { > - struct intel_context *ce = > - to_intel_context(rq->gem_context, rq->engine); > + struct intel_context *ce = rq->hw_context; > struct i915_hw_ppgtt *ppgtt = > rq->gem_context->ppgtt ?: rq->i915->mm.aliasing_ppgtt; > u32 *reg_state = ce->lrc_reg_state; > @@ -496,14 +491,14 @@ static void execlists_submit_ports(struct > intel_engine_cs *engine) > execlists_clear_active(execlists, EXECLISTS_ACTIVE_HWACK); > } > > -static bool ctx_single_port_submission(const struct i915_gem_context *ctx) > +static bool ctx_single_port_submission(const struct intel_context *ce) > { > return (IS_ENABLED(CONFIG_DRM_I915_GVT) && > - i915_gem_context_force_single_submission(ctx)); > + i915_gem_context_force_single_submission(ce->gem_context)); > } > > -static bool can_merge_ctx(const struct i915_gem_context *prev, > - const struct i915_gem_context *next) > +static bool can_merge_ctx(const struct intel_context *prev, > + const struct intel_context *next) > { > if (prev != next) > return false; > @@ -680,8 +675,8 @@ static bool __execlists_dequeue(struct intel_engine_cs > *engine) > * second request, and so we never need to tell the > * hardware about the first. > */ > - if (last && !can_merge_ctx(rq->gem_context, > - last->gem_context)) { > + if (last && > + !can_merge_ctx(rq->hw_context, last->hw_context)) { > /* > * If we are on the second port and cannot > * combine this request with the last, then we > @@ -700,14 +695,14 @@ static bool __execlists_dequeue(struct intel_engine_cs > *engine) > * the same context (even though a different > * request) to the second port. > */ > - if > (ctx_single_port_submission(last->gem_context) || > - > ctx_single_port_submission(rq->gem_context)) { > + if > (ctx_single_port_submission(last->hw_context) || > + ctx_single_port_submission(rq->hw_context)) > { > __list_del_many(&p->requests, > &rq->sched.link); > goto done; > } > > - GEM_BUG_ON(last->gem_context == > rq->gem_context); > + GEM_BUG_ON(last->hw_context == rq->hw_context); > > if (submit) > port_assign(port, last); > @@ -1338,6 +1333,37 @@ static void execlists_schedule(struct i915_request > *request, > spin_unlock_irq(&engine->timeline.lock); > } > > +static void execlists_context_destroy(struct intel_context *ce) > +{ > + GEM_BUG_ON(!ce->state); > + GEM_BUG_ON(ce->pin_count); > + > + intel_ring_free(ce->ring); > + __i915_gem_object_release_unless_active(ce->state->obj); > +} > + > +static void __execlists_context_unpin(struct intel_context *ce) > +{ > + intel_ring_unpin(ce->ring); > + > + ce->state->obj->pin_global--; > + i915_gem_object_unpin_map(ce->state->obj); > + i915_vma_unpin(ce->state); > + > + i915_gem_context_put(ce->gem_context); > +} > + > +static void execlists_context_unpin(struct intel_context *ce) > +{ > + lockdep_assert_held(&ce->gem_context->i915->drm.struct_mutex); > + GEM_BUG_ON(ce->pin_count == 0); > + > + if (--ce->pin_count) > + return; > + > + __execlists_context_unpin(ce); > +} > + > static int __context_pin(struct i915_gem_context *ctx, struct i915_vma *vma) > { > unsigned int flags; > @@ -1361,21 +1387,15 @@ static int __context_pin(struct i915_gem_context > *ctx, struct i915_vma *vma) > return i915_vma_pin(vma, 0, GEN8_LR_CONTEXT_ALIGN, flags); > } > > -static struct intel_ring * > -execlists_context_pin(struct intel_engine_cs *engine, > - struct i915_gem_context *ctx) > +static struct intel_context * > +__execlists_context_pin(struct intel_engine_cs *engine, > + struct i915_gem_context *ctx, > + struct intel_context *ce) > { > - struct intel_context *ce = to_intel_context(ctx, engine); > void *vaddr; > int ret; > > - lockdep_assert_held(&ctx->i915->drm.struct_mutex); > - > - if (likely(ce->pin_count++)) > - goto out; > - GEM_BUG_ON(!ce->pin_count); /* no overflow please! */ > - > - ret = execlists_context_deferred_alloc(ctx, engine); > + ret = execlists_context_deferred_alloc(ctx, engine, ce); > if (ret) > goto err; > GEM_BUG_ON(!ce->state); > @@ -1394,7 +1414,7 @@ execlists_context_pin(struct intel_engine_cs *engine, > if (ret) > goto unpin_map; > > - intel_lr_context_descriptor_update(ctx, engine); > + intel_lr_context_descriptor_update(ctx, engine, ce); > > ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; > ce->lrc_reg_state[CTX_RING_BUFFER_START+1] = > @@ -1403,8 +1423,7 @@ execlists_context_pin(struct intel_engine_cs *engine, > > ce->state->obj->pin_global++; > i915_gem_context_get(ctx); > -out: > - return ce->ring; > + return ce; > > unpin_map: > i915_gem_object_unpin_map(ce->state->obj); > @@ -1415,33 +1434,33 @@ execlists_context_pin(struct intel_engine_cs *engine, > return ERR_PTR(ret); > } > > -static void execlists_context_unpin(struct intel_engine_cs *engine, > - struct i915_gem_context *ctx) > +static const struct intel_context_ops execlists_context_ops = { > + .unpin = execlists_context_unpin, > + .destroy = execlists_context_destroy, > +}; > + > +static struct intel_context * > +execlists_context_pin(struct intel_engine_cs *engine, > + struct i915_gem_context *ctx) > { > struct intel_context *ce = to_intel_context(ctx, engine); > > lockdep_assert_held(&ctx->i915->drm.struct_mutex); > - GEM_BUG_ON(ce->pin_count == 0); > > - if (--ce->pin_count) > - return; > - > - intel_ring_unpin(ce->ring); > + if (likely(ce->pin_count++)) > + return ce; > + GEM_BUG_ON(!ce->pin_count); /* no overflow please! */ > > - ce->state->obj->pin_global--; > - i915_gem_object_unpin_map(ce->state->obj); > - i915_vma_unpin(ce->state); > + ce->ops = &execlists_context_ops; > > - i915_gem_context_put(ctx); > + return __execlists_context_pin(engine, ctx, ce); > } > > static int execlists_request_alloc(struct i915_request *request) > { > - struct intel_context *ce = > - to_intel_context(request->gem_context, request->engine); > int ret; > > - GEM_BUG_ON(!ce->pin_count); > + GEM_BUG_ON(!request->hw_context->pin_count); > > /* Flush enough space to reduce the likelihood of waiting after > * we start building the request - in which case we will just > @@ -1955,7 +1974,7 @@ static void execlists_reset(struct intel_engine_cs > *engine, > * future request will be after userspace has had the opportunity > * to recreate its own state. > */ > - regs = to_intel_context(request->gem_context, engine)->lrc_reg_state; > + regs = request->hw_context->lrc_reg_state; > if (engine->default_state) { > void *defaults; > > @@ -2326,8 +2345,6 @@ logical_ring_default_vfuncs(struct intel_engine_cs > *engine) > engine->reset.finish = execlists_reset_finish; > > engine->context_pin = execlists_context_pin; > - engine->context_unpin = execlists_context_unpin; > - > engine->request_alloc = execlists_request_alloc; > > engine->emit_flush = gen8_emit_flush; > @@ -2562,7 +2579,7 @@ static void execlists_init_reg_state(u32 *regs, > struct drm_i915_private *dev_priv = engine->i915; > struct i915_hw_ppgtt *ppgtt = ctx->ppgtt ?: dev_priv->mm.aliasing_ppgtt; > u32 base = engine->mmio_base; > - bool rcs = engine->id == RCS; > + bool rcs = engine->class == RENDER_CLASS; > > /* A context is actually a big batch buffer with several > * MI_LOAD_REGISTER_IMM commands followed by (reg, value) pairs. The > @@ -2709,10 +2726,10 @@ populate_lr_context(struct i915_gem_context *ctx, > } > > static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, > - struct intel_engine_cs *engine) > + struct intel_engine_cs *engine, > + struct intel_context *ce) > { > struct drm_i915_gem_object *ctx_obj; > - struct intel_context *ce = to_intel_context(ctx, engine); > struct i915_vma *vma; > uint32_t context_size; > struct intel_ring *ring; > diff --git a/drivers/gpu/drm/i915/intel_lrc.h > b/drivers/gpu/drm/i915/intel_lrc.h > index 4ec7d8dd13c8..1593194e930c 100644 > --- a/drivers/gpu/drm/i915/intel_lrc.h > +++ b/drivers/gpu/drm/i915/intel_lrc.h > @@ -104,11 +104,4 @@ struct i915_gem_context; > > void intel_lr_context_resume(struct drm_i915_private *dev_priv); > > -static inline uint64_t > -intel_lr_context_descriptor(struct i915_gem_context *ctx, > - struct intel_engine_cs *engine) > -{ > - return to_intel_context(ctx, engine)->lrc_desc; > -} > - > #endif /* _INTEL_LRC_H_ */ > diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c > b/drivers/gpu/drm/i915/intel_ringbuffer.c > index 53703012ec75..0c0c9f531e4e 100644 > --- a/drivers/gpu/drm/i915/intel_ringbuffer.c > +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c > @@ -571,8 +571,7 @@ static void reset_ring(struct intel_engine_cs *engine, > */ > if (request) { > struct drm_i915_private *dev_priv = request->i915; > - struct intel_context *ce = > - to_intel_context(request->gem_context, engine); > + struct intel_context *ce = request->hw_context; > struct i915_hw_ppgtt *ppgtt; > > if (ce->state) { > @@ -1186,7 +1185,31 @@ intel_ring_free(struct intel_ring *ring) > kfree(ring); > } > > -static int context_pin(struct intel_context *ce) > +static void intel_ring_context_destroy(struct intel_context *ce) > +{ > + GEM_BUG_ON(ce->pin_count); > + > + if (ce->state) > + __i915_gem_object_release_unless_active(ce->state->obj); > +} > + > +static void intel_ring_context_unpin(struct intel_context *ce) > +{ > + lockdep_assert_held(&ce->gem_context->i915->drm.struct_mutex); > + GEM_BUG_ON(ce->pin_count == 0); > + > + if (--ce->pin_count) > + return; > + > + if (ce->state) { > + ce->state->obj->pin_global--; > + i915_vma_unpin(ce->state); > + } > + > + i915_gem_context_put(ce->gem_context); > +} > + > +static int __context_pin(struct intel_context *ce) > { > struct i915_vma *vma = ce->state; > int ret; > @@ -1275,25 +1298,19 @@ alloc_context_vma(struct intel_engine_cs *engine) > return ERR_PTR(err); > } > > -static struct intel_ring * > -intel_ring_context_pin(struct intel_engine_cs *engine, > - struct i915_gem_context *ctx) > +static struct intel_context * > +__ring_context_pin(struct intel_engine_cs *engine, > + struct i915_gem_context *ctx, > + struct intel_context *ce) > { > - struct intel_context *ce = to_intel_context(ctx, engine); > - int ret; > - > - lockdep_assert_held(&ctx->i915->drm.struct_mutex); > - > - if (likely(ce->pin_count++)) > - goto out; > - GEM_BUG_ON(!ce->pin_count); /* no overflow please! */ > + int err; > > if (!ce->state && engine->context_size) { > struct i915_vma *vma; > > vma = alloc_context_vma(engine); > if (IS_ERR(vma)) { > - ret = PTR_ERR(vma); > + err = PTR_ERR(vma); > goto err; > } > > @@ -1301,8 +1318,8 @@ intel_ring_context_pin(struct intel_engine_cs *engine, > } > > if (ce->state) { > - ret = context_pin(ce); > - if (ret) > + err = __context_pin(ce); > + if (err) > goto err; > > ce->state->obj->pin_global++; > @@ -1310,32 +1327,37 @@ intel_ring_context_pin(struct intel_engine_cs *engine, > > i915_gem_context_get(ctx); > > -out: > /* One ringbuffer to rule them all */ > - return engine->buffer; > + GEM_BUG_ON(!engine->buffer); > + ce->ring = engine->buffer; > + > + return ce; > > err: > ce->pin_count = 0; > - return ERR_PTR(ret); > + return ERR_PTR(err); > } > > -static void intel_ring_context_unpin(struct intel_engine_cs *engine, > - struct i915_gem_context *ctx) > +static const struct intel_context_ops ring_context_ops = { > + .unpin = intel_ring_context_unpin, > + .destroy = intel_ring_context_destroy, > +}; > + > +static struct intel_context * > +intel_ring_context_pin(struct intel_engine_cs *engine, > + struct i915_gem_context *ctx) > { > struct intel_context *ce = to_intel_context(ctx, engine); > > lockdep_assert_held(&ctx->i915->drm.struct_mutex); > - GEM_BUG_ON(ce->pin_count == 0); > > - if (--ce->pin_count) > - return; > + if (likely(ce->pin_count++)) > + return ce; > + GEM_BUG_ON(!ce->pin_count); /* no overflow please! */ > > - if (ce->state) { > - ce->state->obj->pin_global--; > - i915_vma_unpin(ce->state); > - } > + ce->ops = &ring_context_ops; > > - i915_gem_context_put(ctx); > + return __ring_context_pin(engine, ctx, ce); > } > > static int intel_init_ring_buffer(struct intel_engine_cs *engine) > @@ -1346,10 +1368,6 @@ static int intel_init_ring_buffer(struct > intel_engine_cs *engine) > > intel_engine_setup_common(engine); > > - err = intel_engine_init_common(engine); > - if (err) > - goto err; > - > timeline = i915_timeline_create(engine->i915, engine->name); > if (IS_ERR(timeline)) { > err = PTR_ERR(timeline); > @@ -1371,8 +1389,14 @@ static int intel_init_ring_buffer(struct > intel_engine_cs *engine) > GEM_BUG_ON(engine->buffer); > engine->buffer = ring; > > + err = intel_engine_init_common(engine); > + if (err) > + goto err_unpin; > + > return 0; > > +err_unpin: > + intel_ring_unpin(ring); > err_ring: > intel_ring_free(ring); > err: > @@ -1458,7 +1482,7 @@ static inline int mi_set_context(struct i915_request > *rq, u32 flags) > > *cs++ = MI_NOOP; > *cs++ = MI_SET_CONTEXT; > - *cs++ = i915_ggtt_offset(to_intel_context(rq->gem_context, > engine)->state) | flags; > + *cs++ = i915_ggtt_offset(rq->hw_context->state) | flags; > /* > * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP > * WaMiSetContext_Hang:snb,ivb,vlv > @@ -1549,7 +1573,7 @@ static int switch_context(struct i915_request *rq) > hw_flags = MI_FORCE_RESTORE; > } > > - if (to_intel_context(to_ctx, engine)->state && > + if (rq->hw_context->state && > (to_ctx != from_ctx || hw_flags & MI_FORCE_RESTORE)) { > GEM_BUG_ON(engine->id != RCS); > > @@ -1597,7 +1621,7 @@ static int ring_request_alloc(struct i915_request > *request) > { > int ret; > > - GEM_BUG_ON(!to_intel_context(request->gem_context, > request->engine)->pin_count); > + GEM_BUG_ON(!request->hw_context->pin_count); > > /* Flush enough space to reduce the likelihood of waiting after > * we start building the request - in which case we will just > @@ -2028,8 +2052,6 @@ static void intel_ring_default_vfuncs(struct > drm_i915_private *dev_priv, > engine->reset.finish = reset_finish; > > engine->context_pin = intel_ring_context_pin; > - engine->context_unpin = intel_ring_context_unpin; > - > engine->request_alloc = ring_request_alloc; > > engine->emit_breadcrumb = i9xx_emit_breadcrumb; > diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h > b/drivers/gpu/drm/i915/intel_ringbuffer.h > index 2b16185e36c4..20c4e13efc0d 100644 > --- a/drivers/gpu/drm/i915/intel_ringbuffer.h > +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h > @@ -436,10 +436,9 @@ struct intel_engine_cs { > > void (*set_default_submission)(struct intel_engine_cs > *engine); > > - struct intel_ring *(*context_pin)(struct intel_engine_cs *engine, > - struct i915_gem_context *ctx); > - void (*context_unpin)(struct intel_engine_cs *engine, > - struct i915_gem_context *ctx); > + struct intel_context *(*context_pin)(struct intel_engine_cs *engine, > + struct i915_gem_context *ctx); > + > int (*request_alloc)(struct i915_request *rq); > int (*init_context)(struct i915_request *rq); > > @@ -555,7 +554,7 @@ struct intel_engine_cs { > * to the kernel context and trash it as the save may not happen > * before the hardware is powered down. > */ > - struct i915_gem_context *last_retired_context; > + struct intel_context *last_retired_context; > > /* We track the current MI_SET_CONTEXT in order to eliminate > * redudant context switches. This presumes that requests are not > diff --git a/drivers/gpu/drm/i915/selftests/mock_context.c > b/drivers/gpu/drm/i915/selftests/mock_context.c > index 501becc47c0c..8904f1ce64e3 100644 > --- a/drivers/gpu/drm/i915/selftests/mock_context.c > +++ b/drivers/gpu/drm/i915/selftests/mock_context.c > @@ -30,6 +30,7 @@ mock_context(struct drm_i915_private *i915, > const char *name) > { > struct i915_gem_context *ctx; > + unsigned int n; > int ret; > > ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); > @@ -43,6 +44,12 @@ mock_context(struct drm_i915_private *i915, > INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL); > INIT_LIST_HEAD(&ctx->handles_list); > > + for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++) { > + struct intel_context *ce = &ctx->__engine[n]; > + > + ce->gem_context = ctx; > + } > + > ret = ida_simple_get(&i915->contexts.hw_ida, > 0, MAX_CONTEXT_HW_ID, GFP_KERNEL); > if (ret < 0) > diff --git a/drivers/gpu/drm/i915/selftests/mock_engine.c > b/drivers/gpu/drm/i915/selftests/mock_engine.c > index 26bf29d97007..33eddfc1f8ce 100644 > --- a/drivers/gpu/drm/i915/selftests/mock_engine.c > +++ b/drivers/gpu/drm/i915/selftests/mock_engine.c > @@ -72,25 +72,37 @@ static void hw_delay_complete(struct timer_list *t) > spin_unlock(&engine->hw_lock); > } > > -static struct intel_ring * > -mock_context_pin(struct intel_engine_cs *engine, > - struct i915_gem_context *ctx) > +static void mock_context_unpin(struct intel_context *ce) > { > - struct intel_context *ce = to_intel_context(ctx, engine); > + if (--ce->pin_count) > + return; > > - if (!ce->pin_count++) > - i915_gem_context_get(ctx); > + i915_gem_context_put(ce->gem_context); > +} > > - return engine->buffer; > +static void mock_context_destroy(struct intel_context *ce) > +{ > + GEM_BUG_ON(ce->pin_count); > } > > -static void mock_context_unpin(struct intel_engine_cs *engine, > - struct i915_gem_context *ctx) > +static const struct intel_context_ops mock_context_ops = { > + .unpin = mock_context_unpin, > + .destroy = mock_context_destroy, > +}; > + > +static struct intel_context * > +mock_context_pin(struct intel_engine_cs *engine, > + struct i915_gem_context *ctx) > { > struct intel_context *ce = to_intel_context(ctx, engine); > > - if (!--ce->pin_count) > - i915_gem_context_put(ctx); > + if (!ce->pin_count++) { > + i915_gem_context_get(ctx); > + ce->ring = engine->buffer; > + ce->ops = &mock_context_ops; > + } > + > + return ce; > } > > static int mock_request_alloc(struct i915_request *request) > @@ -185,7 +197,6 @@ struct intel_engine_cs *mock_engine(struct > drm_i915_private *i915, > engine->base.status_page.page_addr = (void *)(engine + 1); > > engine->base.context_pin = mock_context_pin; > - engine->base.context_unpin = mock_context_unpin; > engine->base.request_alloc = mock_request_alloc; > engine->base.emit_flush = mock_emit_flush; > engine->base.emit_breadcrumb = mock_emit_breadcrumb; > @@ -238,11 +249,13 @@ void mock_engine_free(struct intel_engine_cs *engine) > { > struct mock_engine *mock = > container_of(engine, typeof(*mock), base); > + struct intel_context *ce; > > GEM_BUG_ON(timer_pending(&mock->hw_delay)); > > - if (engine->last_retired_context) > - intel_context_unpin(engine->last_retired_context, engine); > + ce = fetch_and_zero(&engine->last_retired_context); > + if (ce) > + intel_context_unpin(ce); > > mock_ring_free(engine->buffer); > > -- > 2.17.0 > -- Open Source Technology Center, Intel ltd. $gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827
signature.asc
Description: PGP signature
_______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx