From mboxrd@z Thu Jan 1 00:00:00 1970 From: Zhenyu Wang Subject: Re: [PATCH 3/4] drm/i915: Store a pointer to intel_context in i915_request Date: Fri, 18 May 2018 11:21:46 +0800 Message-ID: <20180518032146.iuogvb4ltddj2k4a@zhen-hp.sh.intel.com> References: <20180517212633.24934-1-chris@chris-wilson.co.uk> <20180517212633.24934-3-chris@chris-wilson.co.uk> Reply-To: Zhenyu Wang Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1853506468==" Return-path: Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by gabe.freedesktop.org (Postfix) with ESMTPS id A9C106EC56 for ; Fri, 18 May 2018 03:31:56 +0000 (UTC) In-Reply-To: <20180517212633.24934-3-chris@chris-wilson.co.uk> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" To: Chris Wilson Cc: yan.y.zhao@intel.com, intel-gfx@lists.freedesktop.org List-Id: intel-gfx@lists.freedesktop.org --===============1853506468== Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="kh5sj7dwagwxutci" Content-Disposition: inline --kh5sj7dwagwxutci Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable 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. >=20 > v2: Set mock_context->ops so we don't crash and burn in selftests. > Cleanups from Tvrtko. >=20 > Signed-off-by: Chris Wilson > Cc: Tvrtko Ursulin > --- > 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 > 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(-) >=20 > diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i9= 15/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, struc= t intel_vgpu *next, > =20 > #define CTX_CONTEXT_CONTROL_VAL 0x03 > =20 > -bool is_inhibit_context(struct i915_gem_context *ctx, int ring_id) > +bool is_inhibit_context(struct intel_context *ce) > { > - u32 *reg_state =3D ctx->__engine[ring_id].lrc_reg_state; > + const u32 *reg_state =3D ce->lrc_reg_state; > u32 inhibit_mask =3D > _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); > =20 > @@ -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; > =20 > if (mmio->mask) > diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.h b/drivers/gpu/drm/i9= 15/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, > =20 > void intel_gvt_init_engine_mmio_context(struct intel_gvt *gvt); > =20 > -bool is_inhibit_context(struct i915_gem_context *ctx, int ring_id); > +bool is_inhibit_context(struct intel_context *ce); > =20 > 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( > =20 > static void update_shadow_pdps(struct intel_vgpu_workload *workload) > { > - struct intel_vgpu *vgpu =3D workload->vgpu; > - int ring_id =3D workload->ring_id; > - struct i915_gem_context *shadow_ctx =3D vgpu->submission.shadow_ctx; > struct drm_i915_gem_object *ctx_obj =3D > - shadow_ctx->__engine[ring_id].state->obj; > + workload->req->hw_context->state->obj; > struct execlist_ring_context *shadow_ring_context; > struct page *page; > =20 > @@ -128,9 +125,8 @@ static int populate_shadow_context(struct intel_vgpu_= workload *workload) > struct intel_vgpu *vgpu =3D workload->vgpu; > struct intel_gvt *gvt =3D vgpu->gvt; > int ring_id =3D workload->ring_id; > - struct i915_gem_context *shadow_ctx =3D vgpu->submission.shadow_ctx; > struct drm_i915_gem_object *ctx_obj =3D > - 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 notif= ier_block *nb, > return NOTIFY_OK; > } > =20 > -static void shadow_context_descriptor_update(struct i915_gem_context *ct= x, > - struct intel_engine_cs *engine) > +static void shadow_context_descriptor_update(struct intel_context *ce) > { > - struct intel_context *ce =3D to_intel_context(ctx, engine); > u64 desc =3D 0; > =20 > desc =3D ce->lrc_desc; > @@ -292,7 +286,7 @@ static void shadow_context_descriptor_update(struct i= 915_gem_context *ctx, > * like GEN8_CTX_* cached in desc_template > */ > desc &=3D U64_MAX << 12; > - desc |=3D ctx->desc_template & ((1ULL << 12) - 1); > + desc |=3D ce->gem_context->desc_template & ((1ULL << 12) - 1); > =20 > ce->lrc_desc =3D 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 *work= load) > { > struct intel_vgpu *vgpu =3D workload->vgpu; > + struct i915_request *req =3D workload->req; > void *shadow_ring_buffer_va; > u32 *cs; > - struct i915_request *req =3D workload->req; > =20 > - 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); > =20 > /* 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 =3D &vgpu->submission; > struct i915_gem_context *shadow_ctx =3D s->shadow_ctx; > struct drm_i915_private *dev_priv =3D vgpu->gvt->dev_priv; > - int ring_id =3D workload->ring_id; > - struct intel_engine_cs *engine =3D dev_priv->engine[ring_id]; > - struct intel_ring *ring; > + struct intel_engine_cs *engine =3D dev_priv->engine[workload->ring_id]; > + struct intel_context *ce; > int ret; > =20 > lockdep_assert_held(&dev_priv->drm.struct_mutex); > =20 > - if (workload->shadowed) > + if (workload->req) > return 0; > =20 > + /* 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 =3D 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 &=3D ~(0x3 << GEN8_CTX_ADDRESSING_MODE_SHIFT); > shadow_ctx->desc_template |=3D workload->ctx_desc.addressing_mode << > GEN8_CTX_ADDRESSING_MODE_SHIFT; > =20 > - 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); > =20 > ret =3D intel_gvt_scan_and_shadow_ringbuffer(workload); > if (ret) > - goto err_scan; > + goto err_unpin; > =20 > if ((workload->ring_id =3D=3D RCS) && > (workload->wa_ctx.indirect_ctx.size !=3D 0)) { > ret =3D 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 =3D intel_context_pin(shadow_ctx, engine); > - if (IS_ERR(ring)) { > - ret =3D PTR_ERR(ring); > - gvt_vgpu_err("fail to pin shadow context\n"); > - goto err_shadow; > + goto err_shadow; > } > =20 > ret =3D populate_shadow_context(workload); > if (ret) > - goto err_unpin; > - workload->shadowed =3D true; > + goto err_shadow; > + > return 0; > =20 > -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; > } > =20 > @@ -414,7 +403,6 @@ static int intel_gvt_generate_request(struct intel_vg= pu_workload *workload) > { > int ring_id =3D workload->ring_id; > struct drm_i915_private *dev_priv =3D workload->vgpu->gvt->dev_priv; > - struct intel_engine_cs *engine =3D dev_priv->engine[ring_id]; > struct i915_request *rq; > struct intel_vgpu *vgpu =3D workload->vgpu; > struct intel_vgpu_submission *s =3D &vgpu->submission; > @@ -437,7 +425,6 @@ static int intel_gvt_generate_request(struct intel_vg= pu_workload *workload) > return 0; > =20 > 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; > } > =20 > -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_ct= x) > { > - struct intel_vgpu_workload *workload =3D container_of(wa_ctx, > - struct intel_vgpu_workload, > - wa_ctx); > - int ring_id =3D workload->ring_id; > - struct intel_vgpu_submission *s =3D &workload->vgpu->submission; > - struct i915_gem_context *shadow_ctx =3D s->shadow_ctx; > - struct drm_i915_gem_object *ctx_obj =3D > - shadow_ctx->__engine[ring_id].state->obj; > - struct execlist_ring_context *shadow_ring_context; > - struct page *page; > - > - page =3D i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); > - shadow_ring_context =3D kmap_atomic(page); > + struct intel_vgpu_workload *workload =3D > + container_of(wa_ctx, struct intel_vgpu_workload, wa_ctx); > + struct i915_request *rq =3D workload->req; > + struct execlist_ring_context *shadow_ring_context =3D > + (struct execlist_ring_context *)rq->hw_context->lrc_reg_state; > =20 > shadow_ring_context->bb_per_ctx_ptr.val =3D > (shadow_ring_context->bb_per_ctx_ptr.val & > @@ -539,9 +518,6 @@ static int update_wa_ctx_2_shadow_ctx(struct intel_sh= adow_wa_ctx *wa_ctx) > shadow_ring_context->rcs_indirect_ctx.val =3D > (shadow_ring_context->rcs_indirect_ctx.val & > (~INDIRECT_CTX_ADDR_MASK)) | wa_ctx->indirect_ctx.shadow_gma; > - > - kunmap_atomic(shadow_ring_context); > - return 0; > } > =20 > static int prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) > @@ -670,12 +646,9 @@ static int prepare_workload(struct intel_vgpu_worklo= ad *workload) > static int dispatch_workload(struct intel_vgpu_workload *workload) > { > struct intel_vgpu *vgpu =3D workload->vgpu; > - struct intel_vgpu_submission *s =3D &vgpu->submission; > - struct i915_gem_context *shadow_ctx =3D s->shadow_ctx; > struct drm_i915_private *dev_priv =3D vgpu->gvt->dev_priv; > int ring_id =3D workload->ring_id; > - struct intel_engine_cs *engine =3D dev_priv->engine[ring_id]; > - int ret =3D 0; > + int ret; > =20 > 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_workl= oad *workload) > goto out; > =20 > ret =3D prepare_workload(workload); > - if (ret) { > - intel_context_unpin(shadow_ctx, engine); > - goto out; > - } > =20 > out: > if (ret) > @@ -765,27 +734,23 @@ static struct intel_vgpu_workload *pick_next_worklo= ad( > =20 > static void update_guest_context(struct intel_vgpu_workload *workload) > { > + struct i915_request *rq =3D workload->req; > struct intel_vgpu *vgpu =3D workload->vgpu; > struct intel_gvt *gvt =3D vgpu->gvt; > - struct intel_vgpu_submission *s =3D &vgpu->submission; > - struct i915_gem_context *shadow_ctx =3D s->shadow_ctx; > - int ring_id =3D workload->ring_id; > - struct drm_i915_gem_object *ctx_obj =3D > - shadow_ctx->__engine[ring_id].state->obj; > + struct drm_i915_gem_object *ctx_obj =3D 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; > =20 > - gvt_dbg_sched("ring id %d workload lrca %x\n", ring_id, > - workload->ctx_desc.lrca); > - > - context_page_num =3D 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); > =20 > + context_page_num =3D rq->engine->context_size; > context_page_num =3D context_page_num >> PAGE_SHIFT; > =20 > - if (IS_BROADWELL(gvt->dev_priv) && ring_id =3D=3D RCS) > + if (IS_BROADWELL(gvt->dev_priv) && rq->engine->id =3D=3D RCS) > context_page_num =3D 19; > =20 > i =3D 2; > @@ -858,6 +823,7 @@ static void complete_current_workload(struct intel_gv= t *gvt, int ring_id) > scheduler->current_workload[ring_id]; > struct intel_vgpu *vgpu =3D workload->vgpu; > struct intel_vgpu_submission *s =3D &vgpu->submission; > + struct i915_request *rq; > int event; > =20 > mutex_lock(&gvt->lock); > @@ -866,11 +832,8 @@ static void complete_current_workload(struct intel_g= vt *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 =3D > - workload->vgpu->gvt->dev_priv; > - struct intel_engine_cs *engine =3D > - dev_priv->engine[workload->ring_id]; > + rq =3D fetch_and_zero(&workload->req); > + if (rq) { > wait_event(workload->shadow_ctx_status_wq, > !atomic_read(&workload->shadow_ctx_active)); > =20 > @@ -886,8 +849,6 @@ static void complete_current_workload(struct intel_gv= t *gvt, int ring_id) > workload->status =3D 0; > } > =20 > - 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); > } > =20 > 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); > =20 > workload->status =3D -EINPROGRESS; > - workload->shadowed =3D false; > workload->vgpu =3D vgpu; > =20 > 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; > =20 > 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; > =20 > + struct intel_context *pinned_ctx; > u32 specific_ctx_id; > =20 > 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); > =20 > for_each_engine(engine, dev_priv, id) { > - struct i915_gem_context *ctx; > + struct intel_context *ce; > =20 > i915_gem_reset_engine(engine, > engine->hangcheck.active_request, > stalled_mask & ENGINE_MASK(id)); > - ctx =3D fetch_and_zero(&engine->last_retired_context); > - if (ctx) > - intel_context_unpin(ctx, engine); > + ce =3D fetch_and_zero(&engine->last_retired_context); > + if (ce) > + intel_context_unpin(ce); > =20 > /* > * Ostensibily, we always want a context loaded for powersaving, > @@ -4897,13 +4897,13 @@ void __i915_gem_object_release_unless_active(stru= ct drm_i915_gem_object *obj) > =20 > static void assert_kernel_context_is_current(struct drm_i915_private *i9= 15) > { > - struct i915_gem_context *kernel_context =3D i915->kernel_context; > + struct i915_gem_context *kctx =3D i915->kernel_context; > struct intel_engine_cs *engine; > enum intel_engine_id id; > =20 > for_each_engine(engine, i915, id) { > GEM_BUG_ON(__i915_gem_active_peek(&engine->timeline.last_request)); > - GEM_BUG_ON(engine->last_retired_context !=3D kernel_context); > + GEM_BUG_ON(engine->last_retired_context->gem_context !=3D kctx); > } > } > =20 > diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i9= 15/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_co= ntext *ctx) > for (n =3D 0; n < ARRAY_SIZE(ctx->__engine); n++) { > struct intel_context *ce =3D &ctx->__engine[n]; > =20 > - 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); > } > =20 > 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; > =20 > ctx =3D kzalloc(sizeof(*ctx), GFP_KERNEL); > @@ -283,6 +278,12 @@ __create_hw_context(struct drm_i915_private *dev_pri= v, > ctx->i915 =3D dev_priv; > ctx->sched.priority =3D I915_PRIORITY_NORMAL; > =20 > + for (n =3D 0; n < ARRAY_SIZE(ctx->__engine); n++) { > + struct intel_context *ce =3D &ctx->__engine[n]; > + > + ce->gem_context =3D ctx; > + } > + > INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL); > INIT_LIST_HEAD(&ctx->handles_list); > =20 > diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i9= 15/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; > =20 > #define DEFAULT_CONTEXT_HANDLE 0 > =20 > +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 { > =20 > /** 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]; > =20 > /** 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]; > } > =20 > -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); > } > =20 > -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 =3D to_intel_context(ctx, engine); > - > GEM_BUG_ON(!ce->pin_count); > ce->pin_count++; > } > =20 > -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); > } > =20 > /* 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) > =20 > ee->ctx =3D > i915_error_object_create(i915, > - to_intel_context(ctx, > - engine)->state); > + request->hw_context->state); > =20 > error->simulated |=3D > 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_st= ream *stream) > dev_priv->perf.oa.specific_ctx_id =3D stream->ctx->hw_id; > } else { > struct intel_engine_cs *engine =3D dev_priv->engine[RCS]; > - struct intel_ring *ring; > + struct intel_context *ce; > int ret; > =20 > ret =3D 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 =3D intel_context_pin(stream->ctx, engine); > + ce =3D 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); > =20 > + dev_priv->perf.oa.pinned_ctx =3D ce; > =20 > /* > * 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 =3D > - i915_ggtt_offset(to_intel_context(stream->ctx, engine)->state); > + dev_priv->perf.oa.specific_ctx_id =3D i915_ggtt_offset(ce->state); > } > =20 > 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 =3D stream->dev_priv; > + struct intel_context *ce; > =20 > - if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { > - dev_priv->perf.oa.specific_ctx_id =3D INVALID_CTX_ID; > - } else { > - struct intel_engine_cs *engine =3D dev_priv->engine[RCS]; > + dev_priv->perf.oa.specific_ctx_id =3D INVALID_CTX_ID; > =20 > + ce =3D 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 =3D 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/i= 915_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_engi= ne_cs *engine, > * the subsequent request. > */ > if (engine->last_retired_context) > - intel_context_unpin(engine->last_retired_context, engine); > - engine->last_retired_context =3D rq->gem_context; > + intel_context_unpin(engine->last_retired_context); > + engine->last_retired_context =3D rq->hw_context; > } > =20 > static void __retire_engine_upto(struct intel_engine_cs *engine, > @@ -456,7 +456,7 @@ static void i915_request_retire(struct i915_request *= request) > =20 > /* 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); > =20 > __retire_engine_upto(request->engine, request); > =20 > @@ -657,7 +657,7 @@ i915_request_alloc(struct intel_engine_cs *engine, st= ruct i915_gem_context *ctx) > { > struct drm_i915_private *i915 =3D engine->i915; > struct i915_request *rq; > - struct intel_ring *ring; > + struct intel_context *ce; > int ret; > =20 > 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 =3D intel_context_pin(ctx, engine); > - if (IS_ERR(ring)) > - return ERR_CAST(ring); > - GEM_BUG_ON(!ring); > + ce =3D intel_context_pin(ctx, engine); > + if (IS_ERR(ce)) > + return ERR_CAST(ce); > =20 > ret =3D reserve_gt(i915); > if (ret) > goto err_unpin; > =20 > - ret =3D intel_ring_wait_for_space(ring, MIN_SPACE_FOR_ADD_REQUEST); > + ret =3D intel_ring_wait_for_space(ce->ring, MIN_SPACE_FOR_ADD_REQUEST); > if (ret) > goto err_unreserve; > =20 > /* Move our oldest request to the slab-cache (if not in use!) */ > - rq =3D list_first_entry(&ring->request_list, typeof(*rq), ring_link); > - if (!list_is_last(&rq->ring_link, &ring->request_list) && > + rq =3D 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); > =20 > @@ -761,8 +760,9 @@ i915_request_alloc(struct intel_engine_cs *engine, st= ruct i915_gem_context *ctx) > rq->i915 =3D i915; > rq->engine =3D engine; > rq->gem_context =3D ctx; > - rq->ring =3D ring; > - rq->timeline =3D ring->timeline; > + rq->hw_context =3D ce; > + rq->ring =3D ce->ring; > + rq->timeline =3D ce->ring->timeline; > GEM_BUG_ON(rq->timeline =3D=3D &engine->timeline); > =20 > 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; > =20 > /* Keep a second pin for the dual retirement along engine and ring */ > - __intel_context_pin(rq->gem_context, engine); > + __intel_context_pin(ce); > =20 > /* Check that we didn't interrupt ourselves with a new request */ > GEM_BUG_ON(rq->timeline->seqno !=3D rq->fence.seqno); > return rq; > =20 > err_unwind: > - rq->ring->emit =3D rq->head; > + ce->ring->emit =3D rq->head; > =20 > /* 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, st= ruct i915_gem_context *ctx) > err_unreserve: > unreserve_gt(i915); > err_unpin: > - intel_context_unpin(ctx, engine); > + intel_context_unpin(ce); > return ERR_PTR(ret); > } > =20 > @@ -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 =3D request->engine; > - struct intel_ring *ring =3D request->ring; > struct i915_timeline *timeline =3D request->timeline; > + struct intel_ring *ring =3D 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/i= 915_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/i91= 5/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; > } > =20 > +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 requ= ire 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 =3D engine->i915; > + struct intel_context *ce; > int ret; > =20 > 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 =3D intel_context_pin(engine->i915->kernel_context, engine); > - if (IS_ERR(ring)) > - return PTR_ERR(ring); > + ce =3D intel_context_pin(i915->kernel_context, engine); > + if (IS_ERR(ce)) > + return PTR_ERR(ce); > =20 > /* > * Similarly the preempt context must always be available so that > * we can interrupt the engine at any time. > */ > - if (engine->i915->preempt_context) { > - ring =3D intel_context_pin(engine->i915->preempt_context, engine); > - if (IS_ERR(ring)) { > - ret =3D PTR_ERR(ring); > + if (i915->preempt_context) { > + ce =3D intel_context_pin(i915->preempt_context, engine); > + if (IS_ERR(ce)) { > + ret =3D 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; > =20 > - if (HWS_NEEDS_PHYSICAL(engine->i915)) > + if (HWS_NEEDS_PHYSICAL(i915)) > ret =3D init_phys_status_page(engine); > else > ret =3D 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; > } > =20 > @@ -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 =3D engine->i915; > + > intel_engine_cleanup_scratch(engine); > =20 > 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); > =20 > - 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); > =20 > 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 *engin= e) > { > - const struct i915_gem_context * const kernel_context =3D > - engine->i915->kernel_context; > + const struct intel_context *kernel_context =3D > + to_intel_context(engine->i915->kernel_context, engine); > struct i915_request *rq; > =20 > lockdep_assert_held(&engine->i915->drm.struct_mutex); > @@ -1020,7 +1030,7 @@ bool intel_engine_has_kernel_context(const struct i= ntel_engine_cs *engine) > */ > rq =3D __i915_gem_active_peek(&engine->timeline.last_request); > if (rq) > - return rq->gem_context =3D=3D kernel_context; > + return rq->hw_context =3D=3D kernel_context; > else > return engine->last_retired_context =3D=3D 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; > =20 > lockdep_assert_held(&engine->i915->drm.struct_mutex); > =20 > engine->legacy_active_context =3D NULL; > engine->legacy_active_ppgtt =3D NULL; > =20 > - ctx =3D fetch_and_zero(&engine->last_retired_context); > - if (ctx) > - intel_context_unpin(ctx, engine); > + ce =3D fetch_and_zero(&engine->last_retired_context); > + if (ce) > + intel_context_unpin(ce); > } > =20 > 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/dr= m/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, st= ruct i915_request *rq) > { > struct intel_guc_client *client =3D guc->execbuf_client; > struct intel_engine_cs *engine =3D rq->engine; > - u32 ctx_desc =3D > - lower_32_bits(intel_lr_context_descriptor(rq->gem_context, > - engine)); > + u32 ctx_desc =3D lower_32_bits(rq->hw_context->lrc_desc); > u32 ring_tail =3D intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64); > =20 > 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 =3D guc->preempt_client; > struct guc_stage_desc *stage_desc =3D __get_stage_desc(client); > - u32 ctx_desc =3D lower_32_bits(intel_lr_context_descriptor(client->owne= r, > - engine)); > + u32 ctx_desc =3D lower_32_bits(to_intel_context(client->owner, > + engine)->lrc_desc); > u32 data[7]; > =20 > /* > @@ -726,7 +724,7 @@ static bool __guc_dequeue(struct intel_engine_cs *eng= ine) > struct i915_request *rq, *rn; > =20 > list_for_each_entry_safe(rq, rn, &p->requests, sched.link) { > - if (last && rq->gem_context !=3D last->gem_context) { > + if (last && rq->hw_context !=3D last->hw_context) { > if (port =3D=3D 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/inte= l_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) > =20 > 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_e= ngine_cs *engine, > !i915_request_completed(last)); > } > =20 > -/** > - * intel_lr_context_descriptor_update() - calculate & cache the descript= or > - * 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_en= gine_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 =3D to_intel_context(ctx, engine); > u64 desc; > =20 > BUILD_BUG_ON(MAX_CONTEXT_HW_ID > (BIT(GEN8_CTX_ID_WIDTH))); > @@ -418,8 +414,7 @@ execlists_update_context_pdps(struct i915_hw_ppgtt *p= pgtt, u32 *reg_state) > =20 > static u64 execlists_update_context(struct i915_request *rq) > { > - struct intel_context *ce =3D > - to_intel_context(rq->gem_context, rq->engine); > + struct intel_context *ce =3D rq->hw_context; > struct i915_hw_ppgtt *ppgtt =3D > rq->gem_context->ppgtt ?: rq->i915->mm.aliasing_ppgtt; > u32 *reg_state =3D ce->lrc_reg_state; > @@ -496,14 +491,14 @@ static void execlists_submit_ports(struct intel_eng= ine_cs *engine) > execlists_clear_active(execlists, EXECLISTS_ACTIVE_HWACK); > } > =20 > -static bool ctx_single_port_submission(const struct i915_gem_context *ct= x) > +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)); > } > =20 > -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 !=3D next) > return false; > @@ -680,8 +675,8 @@ static bool __execlists_dequeue(struct intel_engine_c= s *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; > } > =20 > - GEM_BUG_ON(last->gem_context =3D=3D rq->gem_context); > + GEM_BUG_ON(last->hw_context =3D=3D rq->hw_context); > =20 > if (submit) > port_assign(port, last); > @@ -1338,6 +1333,37 @@ static void execlists_schedule(struct i915_request= *request, > spin_unlock_irq(&engine->timeline.lock); > } > =20 > +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 =3D=3D 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); > } > =20 > -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 =3D to_intel_context(ctx, engine); > void *vaddr; > int ret; > =20 > - 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 =3D execlists_context_deferred_alloc(ctx, engine); > + ret =3D 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 *engin= e, > if (ret) > goto unpin_map; > =20 > - intel_lr_context_descriptor_update(ctx, engine); > + intel_lr_context_descriptor_update(ctx, engine, ce); > =20 > ce->lrc_reg_state =3D vaddr + LRC_STATE_PN * PAGE_SIZE; > ce->lrc_reg_state[CTX_RING_BUFFER_START+1] =3D > @@ -1403,8 +1423,7 @@ execlists_context_pin(struct intel_engine_cs *engin= e, > =20 > ce->state->obj->pin_global++; > i915_gem_context_get(ctx); > -out: > - return ce->ring; > + return ce; > =20 > unpin_map: > i915_gem_object_unpin_map(ce->state->obj); > @@ -1415,33 +1434,33 @@ execlists_context_pin(struct intel_engine_cs *eng= ine, > return ERR_PTR(ret); > } > =20 > -static void execlists_context_unpin(struct intel_engine_cs *engine, > - struct i915_gem_context *ctx) > +static const struct intel_context_ops execlists_context_ops =3D { > + .unpin =3D execlists_context_unpin, > + .destroy =3D execlists_context_destroy, > +}; > + > +static struct intel_context * > +execlists_context_pin(struct intel_engine_cs *engine, > + struct i915_gem_context *ctx) > { > struct intel_context *ce =3D to_intel_context(ctx, engine); > =20 > lockdep_assert_held(&ctx->i915->drm.struct_mutex); > - GEM_BUG_ON(ce->pin_count =3D=3D 0); > =20 > - 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! */ > =20 > - ce->state->obj->pin_global--; > - i915_gem_object_unpin_map(ce->state->obj); > - i915_vma_unpin(ce->state); > + ce->ops =3D &execlists_context_ops; > =20 > - i915_gem_context_put(ctx); > + return __execlists_context_pin(engine, ctx, ce); > } > =20 > static int execlists_request_alloc(struct i915_request *request) > { > - struct intel_context *ce =3D > - to_intel_context(request->gem_context, request->engine); > int ret; > =20 > - GEM_BUG_ON(!ce->pin_count); > + GEM_BUG_ON(!request->hw_context->pin_count); > =20 > /* 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 =3D to_intel_context(request->gem_context, engine)->lrc_reg_state; > + regs =3D request->hw_context->lrc_reg_state; > if (engine->default_state) { > void *defaults; > =20 > @@ -2326,8 +2345,6 @@ logical_ring_default_vfuncs(struct intel_engine_cs = *engine) > engine->reset.finish =3D execlists_reset_finish; > =20 > engine->context_pin =3D execlists_context_pin; > - engine->context_unpin =3D execlists_context_unpin; > - > engine->request_alloc =3D execlists_request_alloc; > =20 > engine->emit_flush =3D gen8_emit_flush; > @@ -2562,7 +2579,7 @@ static void execlists_init_reg_state(u32 *regs, > struct drm_i915_private *dev_priv =3D engine->i915; > struct i915_hw_ppgtt *ppgtt =3D ctx->ppgtt ?: dev_priv->mm.aliasing_ppg= tt; > u32 base =3D engine->mmio_base; > - bool rcs =3D engine->id =3D=3D RCS; > + bool rcs =3D engine->class =3D=3D RENDER_CLASS; > =20 > /* 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, > } > =20 > 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 =3D 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/inte= l_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; > =20 > void intel_lr_context_resume(struct drm_i915_private *dev_priv); > =20 > -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/i9= 15/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 =3D request->i915; > - struct intel_context *ce =3D > - to_intel_context(request->gem_context, engine); > + struct intel_context *ce =3D request->hw_context; > struct i915_hw_ppgtt *ppgtt; > =20 > if (ce->state) { > @@ -1186,7 +1185,31 @@ intel_ring_free(struct intel_ring *ring) > kfree(ring); > } > =20 > -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 =3D=3D 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 =3D ce->state; > int ret; > @@ -1275,25 +1298,19 @@ alloc_context_vma(struct intel_engine_cs *engine) > return ERR_PTR(err); > } > =20 > -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 =3D 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; > =20 > if (!ce->state && engine->context_size) { > struct i915_vma *vma; > =20 > vma =3D alloc_context_vma(engine); > if (IS_ERR(vma)) { > - ret =3D PTR_ERR(vma); > + err =3D PTR_ERR(vma); > goto err; > } > =20 > @@ -1301,8 +1318,8 @@ intel_ring_context_pin(struct intel_engine_cs *engi= ne, > } > =20 > if (ce->state) { > - ret =3D context_pin(ce); > - if (ret) > + err =3D __context_pin(ce); > + if (err) > goto err; > =20 > ce->state->obj->pin_global++; > @@ -1310,32 +1327,37 @@ intel_ring_context_pin(struct intel_engine_cs *en= gine, > =20 > i915_gem_context_get(ctx); > =20 > -out: > /* One ringbuffer to rule them all */ > - return engine->buffer; > + GEM_BUG_ON(!engine->buffer); > + ce->ring =3D engine->buffer; > + > + return ce; > =20 > err: > ce->pin_count =3D 0; > - return ERR_PTR(ret); > + return ERR_PTR(err); > } > =20 > -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 =3D { > + .unpin =3D intel_ring_context_unpin, > + .destroy =3D 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 =3D to_intel_context(ctx, engine); > =20 > lockdep_assert_held(&ctx->i915->drm.struct_mutex); > - GEM_BUG_ON(ce->pin_count =3D=3D 0); > =20 > - if (--ce->pin_count) > - return; > + if (likely(ce->pin_count++)) > + return ce; > + GEM_BUG_ON(!ce->pin_count); /* no overflow please! */ > =20 > - if (ce->state) { > - ce->state->obj->pin_global--; > - i915_vma_unpin(ce->state); > - } > + ce->ops =3D &ring_context_ops; > =20 > - i915_gem_context_put(ctx); > + return __ring_context_pin(engine, ctx, ce); > } > =20 > static int intel_init_ring_buffer(struct intel_engine_cs *engine) > @@ -1346,10 +1368,6 @@ static int intel_init_ring_buffer(struct intel_eng= ine_cs *engine) > =20 > intel_engine_setup_common(engine); > =20 > - err =3D intel_engine_init_common(engine); > - if (err) > - goto err; > - > timeline =3D i915_timeline_create(engine->i915, engine->name); > if (IS_ERR(timeline)) { > err =3D PTR_ERR(timeline); > @@ -1371,8 +1389,14 @@ static int intel_init_ring_buffer(struct intel_eng= ine_cs *engine) > GEM_BUG_ON(engine->buffer); > engine->buffer =3D ring; > =20 > + err =3D intel_engine_init_common(engine); > + if (err) > + goto err_unpin; > + > return 0; > =20 > +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_reques= t *rq, u32 flags) > =20 > *cs++ =3D MI_NOOP; > *cs++ =3D MI_SET_CONTEXT; > - *cs++ =3D i915_ggtt_offset(to_intel_context(rq->gem_context, engine)->s= tate) | flags; > + *cs++ =3D 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 =3D MI_FORCE_RESTORE; > } > =20 > - if (to_intel_context(to_ctx, engine)->state && > + if (rq->hw_context->state && > (to_ctx !=3D from_ctx || hw_flags & MI_FORCE_RESTORE)) { > GEM_BUG_ON(engine->id !=3D RCS); > =20 > @@ -1597,7 +1621,7 @@ static int ring_request_alloc(struct i915_request *= request) > { > int ret; > =20 > - GEM_BUG_ON(!to_intel_context(request->gem_context, request->engine)->pi= n_count); > + GEM_BUG_ON(!request->hw_context->pin_count); > =20 > /* 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_i9= 15_private *dev_priv, > engine->reset.finish =3D reset_finish; > =20 > engine->context_pin =3D intel_ring_context_pin; > - engine->context_unpin =3D intel_ring_context_unpin; > - > engine->request_alloc =3D ring_request_alloc; > =20 > engine->emit_breadcrumb =3D i9xx_emit_breadcrumb; > diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i9= 15/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 { > =20 > void (*set_default_submission)(struct intel_engine_cs *engine); > =20 > - 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); > =20 > @@ -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; > =20 > /* 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; > =20 > ctx =3D 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); > =20 > + for (n =3D 0; n < ARRAY_SIZE(ctx->__engine); n++) { > + struct intel_context *ce =3D &ctx->__engine[n]; > + > + ce->gem_context =3D ctx; > + } > + > ret =3D 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/d= rm/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); > } > =20 > -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 =3D to_intel_context(ctx, engine); > + if (--ce->pin_count) > + return; > =20 > - if (!ce->pin_count++) > - i915_gem_context_get(ctx); > + i915_gem_context_put(ce->gem_context); > +} > =20 > - return engine->buffer; > +static void mock_context_destroy(struct intel_context *ce) > +{ > + GEM_BUG_ON(ce->pin_count); > } > =20 > -static void mock_context_unpin(struct intel_engine_cs *engine, > - struct i915_gem_context *ctx) > +static const struct intel_context_ops mock_context_ops =3D { > + .unpin =3D mock_context_unpin, > + .destroy =3D mock_context_destroy, > +}; > + > +static struct intel_context * > +mock_context_pin(struct intel_engine_cs *engine, > + struct i915_gem_context *ctx) > { > struct intel_context *ce =3D to_intel_context(ctx, engine); > =20 > - if (!--ce->pin_count) > - i915_gem_context_put(ctx); > + if (!ce->pin_count++) { > + i915_gem_context_get(ctx); > + ce->ring =3D engine->buffer; > + ce->ops =3D &mock_context_ops; > + } > + > + return ce; > } > =20 > static int mock_request_alloc(struct i915_request *request) > @@ -185,7 +197,6 @@ struct intel_engine_cs *mock_engine(struct drm_i915_p= rivate *i915, > engine->base.status_page.page_addr =3D (void *)(engine + 1); > =20 > engine->base.context_pin =3D mock_context_pin; > - engine->base.context_unpin =3D mock_context_unpin; > engine->base.request_alloc =3D mock_request_alloc; > engine->base.emit_flush =3D mock_emit_flush; > engine->base.emit_breadcrumb =3D mock_emit_breadcrumb; > @@ -238,11 +249,13 @@ void mock_engine_free(struct intel_engine_cs *engin= e) > { > struct mock_engine *mock =3D > container_of(engine, typeof(*mock), base); > + struct intel_context *ce; > =20 > GEM_BUG_ON(timer_pending(&mock->hw_delay)); > =20 > - if (engine->last_retired_context) > - intel_context_unpin(engine->last_retired_context, engine); > + ce =3D fetch_and_zero(&engine->last_retired_context); > + if (ce) > + intel_context_unpin(ce); > =20 > mock_ring_free(engine->buffer); > =20 > --=20 > 2.17.0 >=20 --=20 Open Source Technology Center, Intel ltd. $gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827 --kh5sj7dwagwxutci Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iF0EARECAB0WIQTXuabgHDW6LPt9CICxBBozTXgYJwUCWv5GygAKCRCxBBozTXgY J6MUAKCdkAfuD/SECh4tiTS7m4nqjz/KLgCfcoGuNBWva6ev36+4hzHS1Uz6LrA= =6DB2 -----END PGP SIGNATURE----- --kh5sj7dwagwxutci-- --===============1853506468== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KSW50ZWwtZ2Z4 IG1haWxpbmcgbGlzdApJbnRlbC1nZnhAbGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlz dHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vaW50ZWwtZ2Z4Cg== --===============1853506468==--