[Intel-gfx] [PATCH 14/15] drm/i915/guc: Keep the execbuf client allocated across reset
Tvrtko Ursulin
tvrtko.ursulin at linux.intel.com
Mon Nov 28 13:49:03 UTC 2016
On 25/11/2016 09:30, Chris Wilson wrote:
> In order to avoid some complexity in trying to reconstruct the
> workqueues across reset, remember them instead. The issue comes when we
> have to handle a reset between request allocation and submission, the
> request has reserved space in the wq, but is not in any list so we fail
> to restore the reserved space. By keeping the execbuf client intact
> across the reset, we also keep the reservations.
I lost track a bit on why do we need to reserve the space at request
creation time? Is it not becoming a bit cumbersome?
>
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> ---
> drivers/gpu/drm/i915/i915_guc_submission.c | 83 +++++++++++++++++++-----------
> 1 file changed, 52 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
> index 800dc5bb732f..00b5fa871644 100644
> --- a/drivers/gpu/drm/i915/i915_guc_submission.c
> +++ b/drivers/gpu/drm/i915/i915_guc_submission.c
> @@ -252,13 +252,6 @@ static int guc_update_doorbell_id(struct intel_guc *guc,
> return host2guc_allocate_doorbell(guc, client);
> }
>
> -static int guc_init_doorbell(struct intel_guc *guc,
> - struct i915_guc_client *client,
> - uint16_t db_id)
> -{
> - return guc_update_doorbell_id(guc, client, db_id);
> -}
> -
> static void guc_disable_doorbell(struct intel_guc *guc,
> struct i915_guc_client *client)
> {
> @@ -779,8 +772,7 @@ static void guc_init_doorbell_hw(struct intel_guc *guc)
> uint16_t db_id;
> int i, err;
>
> - /* Save client's original doorbell selection */
> - db_id = client->doorbell_id;
> + guc_disable_doorbell(guc, client);
>
> for (i = 0; i < GUC_MAX_DOORBELLS; ++i) {
> /* Skip if doorbell is OK */
> @@ -793,7 +785,9 @@ static void guc_init_doorbell_hw(struct intel_guc *guc)
> i, err);
> }
>
> - /* Restore to original value */
> + db_id = select_doorbell_register(guc, client->priority);
> + WARN_ON(db_id == GUC_INVALID_DOORBELL_ID);
> +
> err = guc_update_doorbell_id(guc, client, db_id);
> if (err)
> DRM_WARN("Failed to restore doorbell to %d, err %d\n",
> @@ -883,8 +877,13 @@ guc_client_alloc(struct drm_i915_private *dev_priv,
>
> guc_proc_desc_init(guc, client);
> guc_ctx_desc_init(guc, client);
> - if (guc_init_doorbell(guc, client, db_id))
> - goto err;
> +
> + /* For runtime client allocation we need to enable the doorbell. Not
> + * required yet for the static execbuf_client as this special kernel
> + * client is enabled from i915_guc_submission_enable().
> + *
> + * guc_update_doorbell_id(guc, client, db_id);
> + */
What future is the "not yet" part referring to? What are the other clients?
>
> DRM_DEBUG_DRIVER("new priority %u client %p for engine(s) 0x%x: ctx_index %u\n",
> priority, client, client->engines, client->ctx_index);
> @@ -1484,6 +1483,9 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
> struct intel_guc *guc = &dev_priv->guc;
> struct i915_vma *vma;
>
> + if (!HAS_GUC_SCHED(dev_priv))
> + return 0;
Why did you have to add this hunk? I think this function does not get
called unless there is a GuC.
> +
> /* Wipe bitmap & delete client in case of reinitialisation */
> bitmap_clear(guc->doorbell_bitmap, 0, GUC_MAX_DOORBELLS);
> i915_guc_submission_disable(dev_priv);
> @@ -1504,42 +1506,57 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
> guc_log_create(guc);
> guc_addon_create(guc);
>
> + guc->execbuf_client = guc_client_alloc(dev_priv,
> + INTEL_INFO(dev_priv)->ring_mask,
> + GUC_CTX_PRIORITY_KMD_NORMAL,
> + dev_priv->kernel_context);
> + if (!guc->execbuf_client) {
> + DRM_ERROR("Failed to create GuC client for execbuf!\n");
> + goto err;
> + }
> +
> return 0;
> +
> +err:
> + i915_guc_submission_fini(dev_priv);
> + return -ENOMEM;
> +}
> +
> +static void guc_reset_wq(struct i915_guc_client *gc)
> +{
> + struct guc_process_desc *desc = gc->vaddr + gc->proc_desc_offset;
> +
> + desc->head = 0;
> + desc->tail = 0;
> +
> + gc->wq_tail = 0;
> }
>
> int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
> {
> struct intel_guc *guc = &dev_priv->guc;
> - struct drm_i915_gem_request *request;
> - struct i915_guc_client *client;
> + struct i915_guc_client *client = guc->execbuf_client;
> struct intel_engine_cs *engine;
> enum intel_engine_id id;
>
> - /* client for execbuf submission */
> - client = guc_client_alloc(dev_priv,
> - INTEL_INFO(dev_priv)->ring_mask,
> - GUC_CTX_PRIORITY_KMD_NORMAL,
> - dev_priv->kernel_context);
> - if (!client) {
> - DRM_ERROR("Failed to create normal GuC client!\n");
> - return -ENOMEM;
> - }
> + if (!client)
> + return -ENODEV;
>
> - guc->execbuf_client = client;
> + guc_reset_wq(client);
> host2guc_sample_forcewake(guc, client);
> guc_init_doorbell_hw(guc);
>
> /* Take over from manual control of ELSP (execlists) */
> for_each_engine(engine, dev_priv, id) {
> + struct drm_i915_gem_request *rq;
> +
> engine->submit_request = i915_guc_submit;
> engine->schedule = NULL;
>
> /* Replay the current set of previously submitted requests */
> - list_for_each_entry(request,
> - &engine->timeline->requests, link) {
> + list_for_each_entry(rq, &engine->timeline->requests, link) {
> client->wq_rsvd += sizeof(struct guc_wq_item);
> - if (i915_sw_fence_done(&request->submit))
> - i915_guc_submit(request);
i915_sw_fence_done check is not needed because only submit-ready
requests can be on the engine timeline?
> + i915_guc_submit(rq);
> }
> }
>
> @@ -1555,14 +1572,18 @@ void i915_guc_submission_disable(struct drm_i915_private *dev_priv)
>
> /* Revert back to manual ELSP submission */
> intel_execlists_enable_submission(dev_priv);
> -
> - guc_client_free(dev_priv, guc->execbuf_client);
> - guc->execbuf_client = NULL;
> }
>
> void i915_guc_submission_fini(struct drm_i915_private *dev_priv)
> {
> struct intel_guc *guc = &dev_priv->guc;
> + struct i915_guc_client *client;
> +
> + client = fetch_and_zero(&guc->execbuf_client);
> + if (!client)
> + return;
> +
> + guc_client_free(dev_priv, client);
>
> i915_vma_unpin_and_release(&guc->ads_vma);
> i915_vma_unpin_and_release(&guc->log.vma);
>
Regards,
Tvrtko
More information about the Intel-gfx
mailing list