From: Dave Gordon <david.s.gordon@xxxxxxxxx> This second client is created with priority KMD_HIGH, and marked as preemptive. v2: Rebase, cleanup, use an array for the second client. Signed-off-by: Dave Gordon <david.s.gordon@xxxxxxxxx> Signed-off-by: Michał Winiarski <michal.winiarski@xxxxxxxxx> --- drivers/gpu/drm/i915/i915_debugfs.c | 8 +-- drivers/gpu/drm/i915/i915_guc_submission.c | 86 ++++++++++++++++++++---------- drivers/gpu/drm/i915/intel_uc.h | 9 +++- 3 files changed, 71 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1a28b52..10490bf 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2514,7 +2514,7 @@ static int i915_guc_info(struct seq_file *m, void *data) enum intel_engine_id id; u64 total; - if (!guc->execbuf_client) { + if (!guc->client[NORMAL]) { seq_printf(m, "GuC submission %s\n", HAS_GUC_SCHED(dev_priv) ? "disabled" : @@ -2542,8 +2542,10 @@ static int i915_guc_info(struct seq_file *m, void *data) } seq_printf(m, "\t%s: %llu\n", "Total", total); - seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->execbuf_client); - i915_guc_client_info(m, dev_priv, guc->execbuf_client); + seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->client[NORMAL]); + i915_guc_client_info(m, dev_priv, guc->client[NORMAL]); + seq_printf(m, "\nGuC preempt client @ %p:\n", guc->client[PREEMPT]); + i915_guc_client_info(m, dev_priv, guc->client[PREEMPT]); i915_guc_log_info(m, dev_priv); diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 3080735..2a658b9 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -247,6 +247,8 @@ static void guc_ctx_desc_init(struct intel_guc *guc, memset(&desc, 0, sizeof(desc)); desc.attribute = GUC_CTX_DESC_ATTR_ACTIVE | GUC_CTX_DESC_ATTR_KERNEL; + if (client->priority <= GUC_CTX_PRIORITY_HIGH) + desc.attribute |= GUC_CTX_DESC_ATTR_PREEMPT; desc.context_id = client->ctx_index; desc.priority = client->priority; desc.db_id = client->doorbell_id; @@ -344,7 +346,7 @@ static void guc_ctx_desc_fini(struct intel_guc *guc, int i915_guc_wq_reserve(struct drm_i915_gem_request *request) { const size_t wqi_size = sizeof(struct guc_wq_item); - struct i915_guc_client *client = request->i915->guc.execbuf_client; + struct i915_guc_client *client = request->i915->guc.client[NORMAL]; struct guc_process_desc *desc = client->vaddr + client->proc_desc_offset; u32 freespace; @@ -368,7 +370,7 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *request) void i915_guc_wq_unreserve(struct drm_i915_gem_request *request) { const size_t wqi_size = sizeof(struct guc_wq_item); - struct i915_guc_client *client = request->i915->guc.execbuf_client; + struct i915_guc_client *client = request->i915->guc.client[NORMAL]; GEM_BUG_ON(READ_ONCE(client->wq_rsvd) < wqi_size); @@ -518,7 +520,7 @@ static void __i915_guc_submit(struct drm_i915_gem_request *rq) struct intel_engine_cs *engine = rq->engine; unsigned int engine_id = engine->id; struct intel_guc *guc = &rq->i915->guc; - struct i915_guc_client *client = guc->execbuf_client; + struct i915_guc_client *client = guc->client[NORMAL]; int b_ret; spin_lock(&client->wq_lock); @@ -747,8 +749,8 @@ struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size) } static void -guc_client_free(struct drm_i915_private *dev_priv, - struct i915_guc_client *client) +__guc_client_free(struct drm_i915_private *dev_priv, + struct i915_guc_client *client) { struct intel_guc *guc = &dev_priv->guc; @@ -805,7 +807,7 @@ static bool guc_doorbell_check(struct intel_guc *guc, uint16_t db_id) */ static void guc_init_doorbell_hw(struct intel_guc *guc) { - struct i915_guc_client *client = guc->execbuf_client; + struct i915_guc_client *client = guc->client[NORMAL]; uint16_t db_id; int i, err; @@ -836,7 +838,7 @@ static void guc_init_doorbell_hw(struct intel_guc *guc) } /** - * guc_client_alloc() - Allocate an i915_guc_client + * __guc_client_alloc() - Allocate an i915_guc_client * @dev_priv: driver private data structure * @priority: four levels priority _CRITICAL, _HIGH, _NORMAL and _LOW * The kernel client to replace ExecList submission is created with @@ -845,8 +847,8 @@ static void guc_init_doorbell_hw(struct intel_guc *guc) * Return: An i915_guc_client object if success, else NULL. */ static struct i915_guc_client * -guc_client_alloc(struct drm_i915_private *dev_priv, - uint32_t priority) +__guc_client_alloc(struct drm_i915_private *dev_priv, + uint32_t priority) { struct i915_guc_client *client; struct intel_guc *guc = &dev_priv->guc; @@ -910,7 +912,7 @@ guc_client_alloc(struct drm_i915_private *dev_priv, guc_ctx_desc_init(guc, client); /* For runtime client allocation we need to enable the doorbell. Not - * required yet for the static execbuf_client as this special kernel + * required yet for the static client as this special kernel * client is enabled from i915_guc_submission_enable(). * * guc_update_doorbell_id(guc, client, db_id); @@ -924,7 +926,7 @@ guc_client_alloc(struct drm_i915_private *dev_priv, return client; err: - guc_client_free(dev_priv, client); + __guc_client_free(dev_priv, client); return NULL; } @@ -1021,6 +1023,45 @@ static void guc_addon_create(struct intel_guc *guc) kunmap(page); } +static void guc_free_clients(struct drm_i915_private *dev_priv) +{ + struct intel_guc *guc = &dev_priv->guc; + struct i915_guc_client *client; + + client = fetch_and_zero(&guc->client[NORMAL]); + if (client) + __guc_client_free(dev_priv, client); + + client = fetch_and_zero(&guc->client[PREEMPT]); + if (client) + __guc_client_free(dev_priv, client); +} + +static int guc_alloc_clients(struct drm_i915_private *dev_priv) +{ + struct intel_guc *guc = &dev_priv->guc; + + guc->client[NORMAL] = __guc_client_alloc(dev_priv, + GUC_CTX_PRIORITY_KMD_NORMAL); + if (!guc->client[NORMAL]) { + DRM_ERROR("Failed to create GuC client for execbuf!\n"); + goto err; + } + + guc->client[PREEMPT] = __guc_client_alloc(dev_priv, + GUC_CTX_PRIORITY_KMD_HIGH); + if (!guc->client[PREEMPT]) { + DRM_ERROR("Failed to create GuC client for execbuf!\n"); + goto err; + } + + return 0; + +err: + guc_free_clients(dev_priv); + return -ENOMEM; +} + /* * Set up the memory resources to be shared with the GuC. At this point, * we require just one object that can be mapped through the GGTT. @@ -1055,18 +1096,12 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv) intel_guc_log_create(guc); guc_addon_create(guc); - guc->execbuf_client = guc_client_alloc(dev_priv, - GUC_CTX_PRIORITY_KMD_NORMAL); - if (!guc->execbuf_client) { - DRM_ERROR("Failed to create GuC client for execbuf!\n"); - goto err; + if (guc_alloc_clients(dev_priv) != 0) { + i915_guc_submission_fini(dev_priv); + return -ENOMEM; } return 0; - -err: - i915_guc_submission_fini(dev_priv); - return -ENOMEM; } static void guc_reset_wq(struct i915_guc_client *client) @@ -1083,7 +1118,7 @@ static void guc_reset_wq(struct i915_guc_client *client) int i915_guc_submission_enable(struct drm_i915_private *dev_priv) { struct intel_guc *guc = &dev_priv->guc; - struct i915_guc_client *client = guc->execbuf_client; + struct i915_guc_client *client = guc->client[NORMAL]; struct intel_engine_cs *engine; enum intel_engine_id id; @@ -1129,7 +1164,7 @@ void i915_guc_submission_disable(struct drm_i915_private *dev_priv) { struct intel_guc *guc = &dev_priv->guc; - if (!guc->execbuf_client) + if (!guc->client[NORMAL]) return; /* Revert back to manual ELSP submission */ @@ -1139,13 +1174,8 @@ void i915_guc_submission_disable(struct drm_i915_private *dev_priv) 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); + guc_free_clients(dev_priv); i915_vma_unpin_and_release(&guc->ads_vma); i915_vma_unpin_and_release(&guc->log.vma); diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h index d74f4d3..9dcd8fa 100644 --- a/drivers/gpu/drm/i915/intel_uc.h +++ b/drivers/gpu/drm/i915/intel_uc.h @@ -146,6 +146,13 @@ struct intel_guc_log { u32 flush_count[GUC_MAX_LOG_BUFFER]; }; +#define I915_GUC_NUM_CLIENTS 2 + +enum i915_guc_client_id { + NORMAL = 0, + PREEMPT +}; + struct intel_guc { struct intel_uc_fw fw; struct intel_guc_log log; @@ -157,7 +164,7 @@ struct intel_guc { struct i915_vma *ctx_pool_vma; struct ida ctx_ids; - struct i915_guc_client *execbuf_client; + struct i915_guc_client *client[I915_GUC_NUM_CLIENTS]; DECLARE_BITMAP(doorbell_bitmap, GUC_MAX_DOORBELLS); uint32_t db_cacheline; /* Cyclic counter mod pagesize */ -- 2.9.3 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx