From b09935a60d55265027db9f2b0177aa24317b714c Mon Sep 17 00:00:00 2001 From: Oscar Mateo Date: Wed, 22 Mar 2017 10:39:53 -0700 Subject: [PATCH] drm/i915/guc: Refactor the concept "GuC context descriptor" into "GuC stage descriptor" A GuC context and a HW context are in no way related, so the name "GuC context descriptor" is very unfortunate, because a new reader of the code gets overwhelmed very quickly with a lot of things called "context" that refer to different things. We can improve legibility a lot by simply renaming a few objects in the GuC code. v2: - Rebased - s/ctx_desc_pool/stage_desc_pool - Move some explanations to the definition of the guc_stage_desc struct (Chris) v3: - Calculate gemsize with less intermediate steps (Joonas) - Use BIT() macro (Joonas) Signed-off-by: Oscar Mateo Cc: Chris Wilson Cc: Daniele Ceraolo Spurio Reviewed-by: Joonas Lahtinen Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_debugfs.c | 4 +- drivers/gpu/drm/i915/i915_guc_submission.c | 118 +++++++++++---------- drivers/gpu/drm/i915/intel_guc_fwif.h | 48 +++++---- drivers/gpu/drm/i915/intel_guc_loader.c | 4 +- drivers/gpu/drm/i915/intel_uc.h | 8 +- 5 files changed, 96 insertions(+), 86 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e2390df22e08..3ebdbc798f33 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2471,8 +2471,8 @@ static void i915_guc_client_info(struct seq_file *m, enum intel_engine_id id; uint64_t tot = 0; - seq_printf(m, "\tPriority %d, GuC ctx index: %u, PD offset 0x%x\n", - client->priority, client->ctx_index, client->proc_desc_offset); + seq_printf(m, "\tPriority %d, GuC stage index: %u, PD offset 0x%x\n", + client->priority, client->stage_id, client->proc_desc_offset); seq_printf(m, "\tDoorbell id %d, offset: 0x%lx, cookie 0x%x\n", client->doorbell_id, client->doorbell_offset, client->doorbell_cookie); seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n", diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index e2ad365679c3..41ec8af526a5 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -37,16 +37,16 @@ * descriptor and a workqueue (all of them inside a single gem object that * contains all required pages for these elements). * - * GuC context descriptor: + * GuC stage descriptor: * During initialization, the driver allocates a static pool of 1024 such * descriptors, and shares them with the GuC. * Currently, there exists a 1:1 mapping between a i915_guc_client and a - * guc_context_desc (via the client's context_index), so effectively only - * one guc_context_desc gets used. This context descriptor lets the GuC know - * about the doorbell, workqueue and process descriptor. Theoretically, it also - * lets the GuC know about our HW contexts (Context ID, etc...), but we actually + * guc_stage_desc (via the client's stage_id), so effectively only one + * gets used. This stage descriptor lets the GuC know about the doorbell, + * workqueue and process descriptor. Theoretically, it also lets the GuC + * know about our HW contexts (context ID, etc...), but we actually * employ a kind of submission where the GuC uses the LRCA sent via the work - * item instead (the single guc_context_desc associated to execbuf client + * item instead (the single guc_stage_desc associated to execbuf client * contains information about the default kernel context only, but this is * essentially unused). This is called a "proxy" submission. * @@ -82,7 +82,7 @@ static inline bool is_high_priority(struct i915_guc_client* client) { - return client->priority <= GUC_CTX_PRIORITY_HIGH; + return client->priority <= GUC_CLIENT_PRIORITY_HIGH; } static int __reserve_doorbell(struct i915_guc_client *client) @@ -112,7 +112,7 @@ static int __reserve_doorbell(struct i915_guc_client *client) __set_bit(id, client->guc->doorbell_bitmap); client->doorbell_id = id; DRM_DEBUG_DRIVER("client %u (high prio=%s) reserved doorbell: %d\n", - client->ctx_index, yesno(is_high_priority(client)), + client->stage_id, yesno(is_high_priority(client)), id); return 0; } @@ -129,31 +129,31 @@ static void __unreserve_doorbell(struct i915_guc_client *client) * Tell the GuC to allocate or deallocate a specific doorbell */ -static int __guc_allocate_doorbell(struct intel_guc *guc, u32 ctx_index) +static int __guc_allocate_doorbell(struct intel_guc *guc, u32 stage_id) { u32 action[] = { INTEL_GUC_ACTION_ALLOCATE_DOORBELL, - ctx_index + stage_id }; return intel_guc_send(guc, action, ARRAY_SIZE(action)); } -static int __guc_deallocate_doorbell(struct intel_guc *guc, u32 ctx_index) +static int __guc_deallocate_doorbell(struct intel_guc *guc, u32 stage_id) { u32 action[] = { INTEL_GUC_ACTION_DEALLOCATE_DOORBELL, - ctx_index + stage_id }; return intel_guc_send(guc, action, ARRAY_SIZE(action)); } -static struct guc_context_desc *__get_context_desc(struct i915_guc_client *client) +static struct guc_stage_desc *__get_stage_desc(struct i915_guc_client *client) { - struct guc_context_desc *base = client->guc->ctx_pool_vaddr; + struct guc_stage_desc *base = client->guc->stage_desc_pool_vaddr; - return &base[client->ctx_index]; + return &base[client->stage_id]; } /* @@ -165,10 +165,10 @@ static struct guc_context_desc *__get_context_desc(struct i915_guc_client *clien static void __update_doorbell_desc(struct i915_guc_client *client, u16 new_id) { - struct guc_context_desc *desc; + struct guc_stage_desc *desc; /* Update the GuC's idea of the doorbell ID */ - desc = __get_context_desc(client); + desc = __get_stage_desc(client); desc->db_id = new_id; } @@ -194,7 +194,7 @@ static int __create_doorbell(struct i915_guc_client *client) doorbell->db_status = GUC_DOORBELL_ENABLED; doorbell->cookie = client->doorbell_cookie; - err = __guc_allocate_doorbell(client->guc, client->ctx_index); + err = __guc_allocate_doorbell(client->guc, client->stage_id); if (err) { doorbell->db_status = GUC_DOORBELL_DISABLED; doorbell->cookie = 0; @@ -220,7 +220,7 @@ static int __destroy_doorbell(struct i915_guc_client *client) if (wait_for_us(!(I915_READ(GEN8_DRBREGL(db_id)) & GEN8_DRB_VALID), 10)) WARN_ONCE(true, "Doorbell never became invalid after disable\n"); - return __guc_deallocate_doorbell(client->guc, client->ctx_index); + return __guc_deallocate_doorbell(client->guc, client->stage_id); } static int create_doorbell(struct i915_guc_client *client) @@ -301,34 +301,34 @@ static void guc_proc_desc_init(struct intel_guc *guc, desc->wq_base_addr = 0; desc->db_base_addr = 0; - desc->context_id = client->ctx_index; + desc->stage_id = client->stage_id; desc->wq_size_bytes = client->wq_size; desc->wq_status = WQ_STATUS_ACTIVE; desc->priority = client->priority; } /* - * Initialise/clear the context descriptor shared with the GuC firmware. + * Initialise/clear the stage descriptor shared with the GuC firmware. * * This descriptor tells the GuC where (in GGTT space) to find the important * data structures relating to this client (doorbell, process descriptor, * write queue, etc). */ -static void guc_ctx_desc_init(struct intel_guc *guc, - struct i915_guc_client *client) +static void guc_stage_desc_init(struct intel_guc *guc, + struct i915_guc_client *client) { struct drm_i915_private *dev_priv = guc_to_i915(guc); struct intel_engine_cs *engine; struct i915_gem_context *ctx = client->owner; - struct guc_context_desc *desc; + struct guc_stage_desc *desc; unsigned int tmp; u32 gfx_addr; - desc = __get_context_desc(client); + desc = __get_stage_desc(client); memset(desc, 0, sizeof(*desc)); - desc->attribute = GUC_CTX_DESC_ATTR_ACTIVE | GUC_CTX_DESC_ATTR_KERNEL; - desc->context_id = client->ctx_index; + desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE | GUC_STAGE_DESC_ATTR_KERNEL; + desc->stage_id = client->stage_id; desc->priority = client->priority; desc->db_id = client->doorbell_id; @@ -348,7 +348,7 @@ static void guc_ctx_desc_init(struct intel_guc *guc, break; /* XXX: continue? */ /* - * XXX: When this is a GUC_CTX_DESC_ATTR_KERNEL client (proxy + * XXX: When this is a GUC_STAGE_DESC_ATTR_KERNEL client (proxy * submission or, in other words, not using a direct submission * model) the KMD's LRCA is not used for any work submission. * Instead, the GuC uses the LRCA of the user mode context (see @@ -359,7 +359,10 @@ static void guc_ctx_desc_init(struct intel_guc *guc, /* The state page is after PPHWSP */ lrc->ring_lrca = guc_ggtt_offset(ce->state) + LRC_STATE_PN * PAGE_SIZE; - lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) | + + /* XXX: In direct submission, the GuC wants the HW context id + * here. In proxy submission, it wants the stage id */ + lrc->context_id = (client->stage_id << GUC_ELC_CTXID_OFFSET) | (guc_engine_id << GUC_ELC_ENGINE_OFFSET); lrc->ring_begin = guc_ggtt_offset(ce->ring->vma); @@ -390,12 +393,12 @@ static void guc_ctx_desc_init(struct intel_guc *guc, desc->desc_private = (uintptr_t)client; } -static void guc_ctx_desc_fini(struct intel_guc *guc, - struct i915_guc_client *client) +static void guc_stage_desc_fini(struct intel_guc *guc, + struct i915_guc_client *client) { - struct guc_context_desc *desc; + struct guc_stage_desc *desc; - desc = __get_context_desc(client); + desc = __get_stage_desc(client); memset(desc, 0, sizeof(*desc)); } @@ -863,7 +866,7 @@ static int guc_init_doorbell_hw(struct intel_guc *guc) ret = __create_doorbell(client); if (ret) { DRM_ERROR("Couldn't recreate client %u doorbell: %d\n", - client->ctx_index, ret); + client->stage_id, ret); return ret; } } @@ -913,12 +916,12 @@ guc_client_alloc(struct drm_i915_private *dev_priv, client->wq_size = GUC_WQ_SIZE; spin_lock_init(&client->wq_lock); - ret = ida_simple_get(&guc->ctx_ids, 0, GUC_MAX_GPU_CONTEXTS, + ret = ida_simple_get(&guc->stage_ids, 0, GUC_MAX_STAGE_DESCRIPTORS, GFP_KERNEL); if (ret < 0) goto err_client; - client->ctx_index = ret; + client->stage_id = ret; /* The first page is doorbell/proc_desc. Two followed pages are wq. */ vma = intel_guc_allocate_vma(guc, GUC_DB_SIZE + GUC_WQ_SIZE); @@ -950,14 +953,14 @@ guc_client_alloc(struct drm_i915_private *dev_priv, client->proc_desc_offset = (GUC_DB_SIZE / 2); guc_proc_desc_init(guc, client); - guc_ctx_desc_init(guc, client); + guc_stage_desc_init(guc, client); ret = create_doorbell(client); if (ret) goto err_vaddr; - DRM_DEBUG_DRIVER("new priority %u client %p for engine(s) 0x%x: ctx_index %u\n", - priority, client, client->engines, client->ctx_index); + DRM_DEBUG_DRIVER("new priority %u client %p for engine(s) 0x%x: stage_id %u\n", + priority, client, client->engines, client->stage_id); DRM_DEBUG_DRIVER("doorbell id %u, cacheline offset 0x%lx\n", client->doorbell_id, client->doorbell_offset); @@ -968,7 +971,7 @@ err_vaddr: err_vma: i915_vma_unpin_and_release(&client->vma); err_id: - ida_simple_remove(&guc->ctx_ids, client->ctx_index); + ida_simple_remove(&guc->stage_ids, client->stage_id); err_client: kfree(client); return ERR_PTR(ret); @@ -985,10 +988,10 @@ static void guc_client_free(struct i915_guc_client *client) * reset, so we cannot destroy the doorbell properly. Ignore the * error message for now */ destroy_doorbell(client); - guc_ctx_desc_fini(client->guc, client); + guc_stage_desc_fini(client->guc, client); i915_gem_object_unpin_map(client->vma->obj); i915_vma_unpin_and_release(&client->vma); - ida_simple_remove(&client->guc->ctx_ids, client->ctx_index); + ida_simple_remove(&client->guc->stage_ids, client->stage_id); kfree(client); } @@ -1000,7 +1003,7 @@ static void guc_policies_init(struct guc_policies *policies) policies->dpc_promote_time = 500000; policies->max_num_work_items = POLICY_MAX_NUM_WI; - for (p = 0; p < GUC_CTX_PRIORITY_NUM; p++) { + for (p = 0; p < GUC_CLIENT_PRIORITY_NUM; p++) { for (i = GUC_RENDER_ENGINE; i < GUC_MAX_ENGINES_NUM; i++) { policy = &policies->policy[p][i]; @@ -1088,30 +1091,29 @@ static void guc_ads_destroy(struct intel_guc *guc) */ int i915_guc_submission_init(struct drm_i915_private *dev_priv) { - const size_t ctxsize = sizeof(struct guc_context_desc); - const size_t poolsize = GUC_MAX_GPU_CONTEXTS * ctxsize; - const size_t gemsize = round_up(poolsize, PAGE_SIZE); struct intel_guc *guc = &dev_priv->guc; struct i915_vma *vma; void *vaddr; int ret; - if (guc->ctx_pool) + if (guc->stage_desc_pool) return 0; - vma = intel_guc_allocate_vma(guc, gemsize); + vma = intel_guc_allocate_vma(guc, + PAGE_ALIGN(sizeof(struct guc_stage_desc) * + GUC_MAX_STAGE_DESCRIPTORS)); if (IS_ERR(vma)) return PTR_ERR(vma); - guc->ctx_pool = vma; + guc->stage_desc_pool = vma; - vaddr = i915_gem_object_pin_map(guc->ctx_pool->obj, I915_MAP_WB); + vaddr = i915_gem_object_pin_map(guc->stage_desc_pool->obj, I915_MAP_WB); if (IS_ERR(vaddr)) { ret = PTR_ERR(vaddr); goto err_vma; } - guc->ctx_pool_vaddr = vaddr; + guc->stage_desc_pool_vaddr = vaddr; ret = intel_guc_log_create(guc); if (ret < 0) @@ -1121,16 +1123,16 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv) if (ret < 0) goto err_log; - ida_init(&guc->ctx_ids); + ida_init(&guc->stage_ids); return 0; err_log: intel_guc_log_destroy(guc); err_vaddr: - i915_gem_object_unpin_map(guc->ctx_pool->obj); + i915_gem_object_unpin_map(guc->stage_desc_pool->obj); err_vma: - i915_vma_unpin_and_release(&guc->ctx_pool); + i915_vma_unpin_and_release(&guc->stage_desc_pool); return ret; } @@ -1138,11 +1140,11 @@ void i915_guc_submission_fini(struct drm_i915_private *dev_priv) { struct intel_guc *guc = &dev_priv->guc; - ida_destroy(&guc->ctx_ids); + ida_destroy(&guc->stage_ids); guc_ads_destroy(guc); intel_guc_log_destroy(guc); - i915_gem_object_unpin_map(guc->ctx_pool->obj); - i915_vma_unpin_and_release(&guc->ctx_pool); + i915_gem_object_unpin_map(guc->stage_desc_pool->obj); + i915_vma_unpin_and_release(&guc->stage_desc_pool); } static void guc_interrupts_capture(struct drm_i915_private *dev_priv) @@ -1198,7 +1200,7 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) if (!client) { client = guc_client_alloc(dev_priv, INTEL_INFO(dev_priv)->ring_mask, - GUC_CTX_PRIORITY_KMD_NORMAL, + GUC_CLIENT_PRIORITY_KMD_NORMAL, dev_priv->kernel_context); if (IS_ERR(client)) { DRM_ERROR("Failed to create GuC client for execbuf!\n"); diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 4edf40fe361f..18131b7289a5 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -26,14 +26,14 @@ #define GFXCORE_FAMILY_GEN9 12 #define GFXCORE_FAMILY_UNKNOWN 0x7fffffff -#define GUC_CTX_PRIORITY_KMD_HIGH 0 -#define GUC_CTX_PRIORITY_HIGH 1 -#define GUC_CTX_PRIORITY_KMD_NORMAL 2 -#define GUC_CTX_PRIORITY_NORMAL 3 -#define GUC_CTX_PRIORITY_NUM 4 +#define GUC_CLIENT_PRIORITY_KMD_HIGH 0 +#define GUC_CLIENT_PRIORITY_HIGH 1 +#define GUC_CLIENT_PRIORITY_KMD_NORMAL 2 +#define GUC_CLIENT_PRIORITY_NORMAL 3 +#define GUC_CLIENT_PRIORITY_NUM 4 -#define GUC_MAX_GPU_CONTEXTS 1024 -#define GUC_INVALID_CTX_ID GUC_MAX_GPU_CONTEXTS +#define GUC_MAX_STAGE_DESCRIPTORS 1024 +#define GUC_INVALID_STAGE_ID GUC_MAX_STAGE_DESCRIPTORS #define GUC_RENDER_ENGINE 0 #define GUC_VIDEO_ENGINE 1 @@ -68,14 +68,14 @@ #define GUC_DOORBELL_ENABLED 1 #define GUC_DOORBELL_DISABLED 0 -#define GUC_CTX_DESC_ATTR_ACTIVE (1 << 0) -#define GUC_CTX_DESC_ATTR_PENDING_DB (1 << 1) -#define GUC_CTX_DESC_ATTR_KERNEL (1 << 2) -#define GUC_CTX_DESC_ATTR_PREEMPT (1 << 3) -#define GUC_CTX_DESC_ATTR_RESET (1 << 4) -#define GUC_CTX_DESC_ATTR_WQLOCKED (1 << 5) -#define GUC_CTX_DESC_ATTR_PCH (1 << 6) -#define GUC_CTX_DESC_ATTR_TERMINATED (1 << 7) +#define GUC_STAGE_DESC_ATTR_ACTIVE BIT(0) +#define GUC_STAGE_DESC_ATTR_PENDING_DB BIT(1) +#define GUC_STAGE_DESC_ATTR_KERNEL BIT(2) +#define GUC_STAGE_DESC_ATTR_PREEMPT BIT(3) +#define GUC_STAGE_DESC_ATTR_RESET BIT(4) +#define GUC_STAGE_DESC_ATTR_WQLOCKED BIT(5) +#define GUC_STAGE_DESC_ATTR_PCH BIT(6) +#define GUC_STAGE_DESC_ATTR_TERMINATED BIT(7) /* The guc control data is 10 DWORDs */ #define GUC_CTL_CTXINFO 0 @@ -256,7 +256,7 @@ struct guc_wq_item { } __packed; struct guc_process_desc { - u32 context_id; + u32 stage_id; u64 db_base_addr; u32 head; u32 tail; @@ -289,10 +289,18 @@ struct guc_execlist_context { u16 engine_submit_queue_count; } __packed; -/*Context descriptor for communicating between uKernel and Driver*/ -struct guc_context_desc { +/* + * This structure describes a stage set arranged for a particular communication + * between uKernel (GuC) and Driver (KMD). Technically, this is known as a + * "GuC Context descriptor" in the specs, but we use the term "stage descriptor" + * to avoid confusion with all the other things already named "context" in the + * driver. A static pool of these descriptors are stored inside a GEM object + * (stage_desc_pool) which is held for the entire lifetime of our interaction + * with the GuC, being allocated before the GuC is loaded with its firmware. + */ +struct guc_stage_desc { u32 sched_common_area; - u32 context_id; + u32 stage_id; u32 pas_id; u8 engines_used; u64 db_trigger_cpu; @@ -359,7 +367,7 @@ struct guc_policy { } __packed; struct guc_policies { - struct guc_policy policy[GUC_CTX_PRIORITY_NUM][GUC_MAX_ENGINES_NUM]; + struct guc_policy policy[GUC_CLIENT_PRIORITY_NUM][GUC_MAX_ENGINES_NUM]; /* In micro seconds. How much time to allow before DPC processing is * called back via interrupt (to prevent DPC queue drain starving). diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 62ebf5605f6e..7d92321f8731 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -151,8 +151,8 @@ static void guc_params_init(struct drm_i915_private *dev_priv) /* If GuC submission is enabled, set up additional parameters here */ if (i915.enable_guc_submission) { u32 ads = guc_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT; - u32 pgs = guc_ggtt_offset(dev_priv->guc.ctx_pool); - u32 ctx_in_16 = GUC_MAX_GPU_CONTEXTS / 16; + u32 pgs = guc_ggtt_offset(dev_priv->guc.stage_desc_pool); + u32 ctx_in_16 = GUC_MAX_STAGE_DESCRIPTORS / 16; params[GUC_CTL_DEBUG] |= ads << GUC_ADS_ADDR_SHIFT; params[GUC_CTL_DEBUG] |= GUC_ADS_ENABLED; diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h index 65d0b5918661..6cf2d14fa0dc 100644 --- a/drivers/gpu/drm/i915/intel_uc.h +++ b/drivers/gpu/drm/i915/intel_uc.h @@ -74,7 +74,7 @@ struct i915_guc_client { uint32_t engines; /* bitmap of (host) engine ids */ uint32_t priority; - u32 ctx_index; + u32 stage_id; uint32_t proc_desc_offset; u16 doorbell_id; @@ -157,9 +157,9 @@ struct intel_guc { bool interrupts_enabled; struct i915_vma *ads_vma; - struct i915_vma *ctx_pool; - void *ctx_pool_vaddr; - struct ida ctx_ids; + struct i915_vma *stage_desc_pool; + void *stage_desc_pool_vaddr; + struct ida stage_ids; struct i915_guc_client *execbuf_client; -- 2.20.1