[Intel-gfx] [PATCH 1/1] drm/i915/guc: Update to GuC version 70.1.1

Matt Roper matthew.d.roper at intel.com
Fri Apr 15 00:14:55 UTC 2022


On Tue, Apr 12, 2022 at 03:59:55PM -0700, John.C.Harrison at Intel.com wrote:
> From: John Harrison <John.C.Harrison at Intel.com>
> 
> The latest GuC firmware drops the context descriptor pool in favour of
> passing all creation data in the create H2G. It also greatly simplifies
> the work queue and removes the process descriptor used for multi-LRC
> submission. So, remove all mention of LRC and process descriptors and
> update the registration code accordingly.
> 
> Unfortunately, the new API also removes the ability to set default
> values for the scheduling policies at context registration time.
> Instead, a follow up H2G must be sent. The individual scheduling
> policy update H2G commands are also dropped in favour of a single KLV
> based H2G. So, change the update wrappers accordingly and call this
> during context registration..
> 
> Of course, this second H2G per registration might fail due to being
> backed up. The registration code has a complicated state machine to
> cope with the actual registration call failing. However, if that works
> then there is no support for unwinding if a further call should fail.
> Unwinding would require sending a H2G to de-register - but that can't
> be done because the CTB is already backed up.
> 
> So instead, add a new flag to say whether the context has a pending
> policy update. This is set if the policy H2G fails at registration
> time. The submission code checks for this flag and retries the policy
> update if set. If that call fails, the submission path early exists
> with a retry error. This is something that is already supported for
> other reasons.
> 
> Signed-off-by: John Harrison <John.C.Harrison at Intel.com>
> Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>

Applied to drm-intel-gt-next.  Thanks for the patch and review.


Matt

> ---
>  .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |   4 +-
>  drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h |  15 +
>  drivers/gpu/drm/i915/gt/uc/intel_guc.h        |   5 -
>  drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h   |  67 ++--
>  .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 375 +++++++++++-------
>  drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c      |  32 +-
>  6 files changed, 294 insertions(+), 204 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
> index 9ad6df1b6fbc..be9ac47fa9d0 100644
> --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
> +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
> @@ -122,11 +122,9 @@ enum intel_guc_action {
>  	INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_DONE = 0x1002,
>  	INTEL_GUC_ACTION_SCHED_ENGINE_MODE_SET = 0x1003,
>  	INTEL_GUC_ACTION_SCHED_ENGINE_MODE_DONE = 0x1004,
> -	INTEL_GUC_ACTION_SET_CONTEXT_PRIORITY = 0x1005,
> -	INTEL_GUC_ACTION_SET_CONTEXT_EXECUTION_QUANTUM = 0x1006,
> -	INTEL_GUC_ACTION_SET_CONTEXT_PREEMPTION_TIMEOUT = 0x1007,
>  	INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION = 0x1008,
>  	INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009,
> +	INTEL_GUC_ACTION_HOST2GUC_UPDATE_CONTEXT_POLICIES = 0x100B,
>  	INTEL_GUC_ACTION_SETUP_PC_GUCRC = 0x3004,
>  	INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
>  	INTEL_GUC_ACTION_GET_HWCONFIG = 0x4100,
> diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
> index f0814a57c191..4a59478c3b5c 100644
> --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
> +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
> @@ -6,6 +6,8 @@
>  #ifndef _ABI_GUC_KLVS_ABI_H
>  #define _ABI_GUC_KLVS_ABI_H
>  
> +#include <linux/types.h>
> +
>  /**
>   * DOC: GuC KLV
>   *
> @@ -79,4 +81,17 @@
>  #define GUC_KLV_SELF_CFG_G2H_CTB_SIZE_KEY		0x0907
>  #define GUC_KLV_SELF_CFG_G2H_CTB_SIZE_LEN		1u
>  
> +/*
> + * Per context scheduling policy update keys.
> + */
> +enum  {
> +	GUC_CONTEXT_POLICIES_KLV_ID_EXECUTION_QUANTUM			= 0x2001,
> +	GUC_CONTEXT_POLICIES_KLV_ID_PREEMPTION_TIMEOUT			= 0x2002,
> +	GUC_CONTEXT_POLICIES_KLV_ID_SCHEDULING_PRIORITY			= 0x2003,
> +	GUC_CONTEXT_POLICIES_KLV_ID_PREEMPT_TO_IDLE_ON_QUANTUM_EXPIRY	= 0x2004,
> +	GUC_CONTEXT_POLICIES_KLV_ID_SLPM_GT_FREQUENCY			= 0x2005,
> +
> +	GUC_CONTEXT_POLICIES_KLV_NUM_IDS = 5,
> +};
> +
>  #endif /* _ABI_GUC_KLVS_ABI_H */
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> index 4e431c14b118..3f3373f68123 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> @@ -170,11 +170,6 @@ struct intel_guc {
>  	/** @ads_engine_usage_size: size of engine usage in the ADS */
>  	u32 ads_engine_usage_size;
>  
> -	/** @lrc_desc_pool: object allocated to hold the GuC LRC descriptor pool */
> -	struct i915_vma *lrc_desc_pool;
> -	/** @lrc_desc_pool_vaddr: contents of the GuC LRC descriptor pool */
> -	void *lrc_desc_pool_vaddr;
> -
>  	/**
>  	 * @context_lookup: used to resolve intel_context from guc_id, if a
>  	 * context is present in this structure it is registered with the GuC
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> index f21b6de46a99..c154b5efccde 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> @@ -197,54 +197,45 @@ struct guc_wq_item {
>  	u32 fence_id;
>  } __packed;
>  
> -struct guc_process_desc {
> -	u32 stage_id;
> -	u64 db_base_addr;
> +struct guc_sched_wq_desc {
>  	u32 head;
>  	u32 tail;
>  	u32 error_offset;
> -	u64 wq_base_addr;
> -	u32 wq_size_bytes;
>  	u32 wq_status;
> -	u32 engine_presence;
> -	u32 priority;
> -	u32 reserved[36];
> +	u32 reserved[28];
>  } __packed;
>  
> +/* Helper for context registration H2G */
> +struct guc_ctxt_registration_info {
> +	u32 flags;
> +	u32 context_idx;
> +	u32 engine_class;
> +	u32 engine_submit_mask;
> +	u32 wq_desc_lo;
> +	u32 wq_desc_hi;
> +	u32 wq_base_lo;
> +	u32 wq_base_hi;
> +	u32 wq_size;
> +	u32 hwlrca_lo;
> +	u32 hwlrca_hi;
> +};
>  #define CONTEXT_REGISTRATION_FLAG_KMD	BIT(0)
>  
> -#define CONTEXT_POLICY_DEFAULT_EXECUTION_QUANTUM_US 1000000
> -#define CONTEXT_POLICY_DEFAULT_PREEMPTION_TIME_US 500000
> +/* 32-bit KLV structure as used by policy updates and others */
> +struct guc_klv_generic_dw_t {
> +	u32 kl;
> +	u32 value;
> +} __packed;
>  
> -/* Preempt to idle on quantum expiry */
> -#define CONTEXT_POLICY_FLAG_PREEMPT_TO_IDLE	BIT(0)
> +/* Format of the UPDATE_CONTEXT_POLICIES H2G data packet */
> +struct guc_update_context_policy_header {
> +	u32 action;
> +	u32 ctx_id;
> +} __packed;
>  
> -/*
> - * GuC Context registration descriptor.
> - * FIXME: This is only required to exist during context registration.
> - * The current 1:1 between guc_lrc_desc and LRCs for the lifetime of the LRC
> - * is not required.
> - */
> -struct guc_lrc_desc {
> -	u32 hw_context_desc;
> -	u32 slpm_perf_mode_hint;	/* SPLC v1 only */
> -	u32 slpm_freq_hint;
> -	u32 engine_submit_mask;		/* In logical space */
> -	u8 engine_class;
> -	u8 reserved0[3];
> -	u32 priority;
> -	u32 process_desc;
> -	u32 wq_addr;
> -	u32 wq_size;
> -	u32 context_flags;		/* CONTEXT_REGISTRATION_* */
> -	/* Time for one workload to execute. (in micro seconds) */
> -	u32 execution_quantum;
> -	/* Time to wait for a preemption request to complete before issuing a
> -	 * reset. (in micro seconds).
> -	 */
> -	u32 preemption_timeout;
> -	u32 policy_flags;		/* CONTEXT_POLICY_* */
> -	u32 reserved1[19];
> +struct guc_update_context_policy {
> +	struct guc_update_context_policy_header header;
> +	struct guc_klv_generic_dw_t klv[GUC_CONTEXT_POLICIES_KLV_NUM_IDS];
>  } __packed;
>  
>  #define GUC_POWER_UNSPECIFIED	0
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
> index e1612c393781..ee45fdb67f32 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
> @@ -162,7 +162,8 @@ guc_create_parallel(struct intel_engine_cs **engines,
>  #define SCHED_STATE_ENABLED				BIT(4)
>  #define SCHED_STATE_PENDING_ENABLE			BIT(5)
>  #define SCHED_STATE_REGISTERED				BIT(6)
> -#define SCHED_STATE_BLOCKED_SHIFT			7
> +#define SCHED_STATE_POLICY_REQUIRED			BIT(7)
> +#define SCHED_STATE_BLOCKED_SHIFT			8
>  #define SCHED_STATE_BLOCKED		BIT(SCHED_STATE_BLOCKED_SHIFT)
>  #define SCHED_STATE_BLOCKED_MASK	(0xfff << SCHED_STATE_BLOCKED_SHIFT)
>  
> @@ -301,6 +302,23 @@ static inline void clr_context_registered(struct intel_context *ce)
>  	ce->guc_state.sched_state &= ~SCHED_STATE_REGISTERED;
>  }
>  
> +static inline bool context_policy_required(struct intel_context *ce)
> +{
> +	return ce->guc_state.sched_state & SCHED_STATE_POLICY_REQUIRED;
> +}
> +
> +static inline void set_context_policy_required(struct intel_context *ce)
> +{
> +	lockdep_assert_held(&ce->guc_state.lock);
> +	ce->guc_state.sched_state |= SCHED_STATE_POLICY_REQUIRED;
> +}
> +
> +static inline void clr_context_policy_required(struct intel_context *ce)
> +{
> +	lockdep_assert_held(&ce->guc_state.lock);
> +	ce->guc_state.sched_state &= ~SCHED_STATE_POLICY_REQUIRED;
> +}
> +
>  static inline u32 context_blocked(struct intel_context *ce)
>  {
>  	return (ce->guc_state.sched_state & SCHED_STATE_BLOCKED_MASK) >>
> @@ -396,12 +414,12 @@ struct sync_semaphore {
>  };
>  
>  struct parent_scratch {
> -	struct guc_process_desc pdesc;
> +	struct guc_sched_wq_desc wq_desc;
>  
>  	struct sync_semaphore go;
>  	struct sync_semaphore join[MAX_ENGINE_INSTANCE + 1];
>  
> -	u8 unused[WQ_OFFSET - sizeof(struct guc_process_desc) -
> +	u8 unused[WQ_OFFSET - sizeof(struct guc_sched_wq_desc) -
>  		sizeof(struct sync_semaphore) * (MAX_ENGINE_INSTANCE + 2)];
>  
>  	u32 wq[WQ_SIZE / sizeof(u32)];
> @@ -438,15 +456,15 @@ __get_parent_scratch(struct intel_context *ce)
>  		   LRC_STATE_OFFSET) / sizeof(u32)));
>  }
>  
> -static struct guc_process_desc *
> -__get_process_desc(struct intel_context *ce)
> +static struct guc_sched_wq_desc *
> +__get_wq_desc(struct intel_context *ce)
>  {
>  	struct parent_scratch *ps = __get_parent_scratch(ce);
>  
> -	return &ps->pdesc;
> +	return &ps->wq_desc;
>  }
>  
> -static u32 *get_wq_pointer(struct guc_process_desc *desc,
> +static u32 *get_wq_pointer(struct guc_sched_wq_desc *wq_desc,
>  			   struct intel_context *ce,
>  			   u32 wqi_size)
>  {
> @@ -458,7 +476,7 @@ static u32 *get_wq_pointer(struct guc_process_desc *desc,
>  #define AVAILABLE_SPACE	\
>  	CIRC_SPACE(ce->parallel.guc.wqi_tail, ce->parallel.guc.wqi_head, WQ_SIZE)
>  	if (wqi_size > AVAILABLE_SPACE) {
> -		ce->parallel.guc.wqi_head = READ_ONCE(desc->head);
> +		ce->parallel.guc.wqi_head = READ_ONCE(wq_desc->head);
>  
>  		if (wqi_size > AVAILABLE_SPACE)
>  			return NULL;
> @@ -468,15 +486,6 @@ static u32 *get_wq_pointer(struct guc_process_desc *desc,
>  	return &__get_parent_scratch(ce)->wq[ce->parallel.guc.wqi_tail / sizeof(u32)];
>  }
>  
> -static struct guc_lrc_desc *__get_lrc_desc(struct intel_guc *guc, u32 index)
> -{
> -	struct guc_lrc_desc *base = guc->lrc_desc_pool_vaddr;
> -
> -	GEM_BUG_ON(index >= GUC_MAX_CONTEXT_ID);
> -
> -	return &base[index];
> -}
> -
>  static inline struct intel_context *__get_context(struct intel_guc *guc, u32 id)
>  {
>  	struct intel_context *ce = xa_load(&guc->context_lookup, id);
> @@ -486,39 +495,11 @@ static inline struct intel_context *__get_context(struct intel_guc *guc, u32 id)
>  	return ce;
>  }
>  
> -static int guc_lrc_desc_pool_create(struct intel_guc *guc)
> -{
> -	u32 size;
> -	int ret;
> -
> -	size = PAGE_ALIGN(sizeof(struct guc_lrc_desc) *
> -			  GUC_MAX_CONTEXT_ID);
> -	ret = intel_guc_allocate_and_map_vma(guc, size, &guc->lrc_desc_pool,
> -					     (void **)&guc->lrc_desc_pool_vaddr);
> -	if (ret)
> -		return ret;
> -
> -	return 0;
> -}
> -
> -static void guc_lrc_desc_pool_destroy(struct intel_guc *guc)
> -{
> -	guc->lrc_desc_pool_vaddr = NULL;
> -	i915_vma_unpin_and_release(&guc->lrc_desc_pool, I915_VMA_RELEASE_MAP);
> -}
> -
>  static inline bool guc_submission_initialized(struct intel_guc *guc)
>  {
>  	return guc->submission_initialized;
>  }
>  
> -static inline void _reset_lrc_desc(struct intel_guc *guc, u32 id)
> -{
> -	struct guc_lrc_desc *desc = __get_lrc_desc(guc, id);
> -
> -	memset(desc, 0, sizeof(*desc));
> -}
> -
>  static inline bool ctx_id_mapped(struct intel_guc *guc, u32 id)
>  {
>  	return __get_context(guc, id);
> @@ -545,8 +526,6 @@ static inline void clr_ctx_id_mapping(struct intel_guc *guc, u32 id)
>  	if (unlikely(!guc_submission_initialized(guc)))
>  		return;
>  
> -	_reset_lrc_desc(guc, id);
> -
>  	/*
>  	 * xarray API doesn't have xa_erase_irqsave wrapper, so calling
>  	 * the lower level functions directly.
> @@ -632,6 +611,7 @@ int intel_guc_wait_for_idle(struct intel_guc *guc, long timeout)
>  					      true, timeout);
>  }
>  
> +static int guc_context_policy_init(struct intel_context *ce, bool loop);
>  static int try_context_registration(struct intel_context *ce, bool loop);
>  
>  static int __guc_add_request(struct intel_guc *guc, struct i915_request *rq)
> @@ -658,6 +638,12 @@ static int __guc_add_request(struct intel_guc *guc, struct i915_request *rq)
>  	GEM_BUG_ON(!atomic_read(&ce->guc_id.ref));
>  	GEM_BUG_ON(context_guc_id_invalid(ce));
>  
> +	if (context_policy_required(ce)) {
> +		err = guc_context_policy_init(ce, false);
> +		if (err)
> +			return err;
> +	}
> +
>  	spin_lock(&ce->guc_state.lock);
>  
>  	/*
> @@ -751,7 +737,7 @@ static u32 wq_space_until_wrap(struct intel_context *ce)
>  	return (WQ_SIZE - ce->parallel.guc.wqi_tail);
>  }
>  
> -static void write_wqi(struct guc_process_desc *desc,
> +static void write_wqi(struct guc_sched_wq_desc *wq_desc,
>  		      struct intel_context *ce,
>  		      u32 wqi_size)
>  {
> @@ -764,13 +750,13 @@ static void write_wqi(struct guc_process_desc *desc,
>  
>  	ce->parallel.guc.wqi_tail = (ce->parallel.guc.wqi_tail + wqi_size) &
>  		(WQ_SIZE - 1);
> -	WRITE_ONCE(desc->tail, ce->parallel.guc.wqi_tail);
> +	WRITE_ONCE(wq_desc->tail, ce->parallel.guc.wqi_tail);
>  }
>  
>  static int guc_wq_noop_append(struct intel_context *ce)
>  {
> -	struct guc_process_desc *desc = __get_process_desc(ce);
> -	u32 *wqi = get_wq_pointer(desc, ce, wq_space_until_wrap(ce));
> +	struct guc_sched_wq_desc *wq_desc = __get_wq_desc(ce);
> +	u32 *wqi = get_wq_pointer(wq_desc, ce, wq_space_until_wrap(ce));
>  	u32 len_dw = wq_space_until_wrap(ce) / sizeof(u32) - 1;
>  
>  	if (!wqi)
> @@ -789,7 +775,7 @@ static int __guc_wq_item_append(struct i915_request *rq)
>  {
>  	struct intel_context *ce = request_to_scheduling_context(rq);
>  	struct intel_context *child;
> -	struct guc_process_desc *desc = __get_process_desc(ce);
> +	struct guc_sched_wq_desc *wq_desc = __get_wq_desc(ce);
>  	unsigned int wqi_size = (ce->parallel.number_children + 4) *
>  		sizeof(u32);
>  	u32 *wqi;
> @@ -809,7 +795,7 @@ static int __guc_wq_item_append(struct i915_request *rq)
>  			return ret;
>  	}
>  
> -	wqi = get_wq_pointer(desc, ce, wqi_size);
> +	wqi = get_wq_pointer(wq_desc, ce, wqi_size);
>  	if (!wqi)
>  		return -EBUSY;
>  
> @@ -824,7 +810,7 @@ static int __guc_wq_item_append(struct i915_request *rq)
>  	for_each_child(ce, child)
>  		*wqi++ = child->ring->tail / sizeof(u64);
>  
> -	write_wqi(desc, ce, wqi_size);
> +	write_wqi(wq_desc, ce, wqi_size);
>  
>  	return 0;
>  }
> @@ -1812,20 +1798,10 @@ static void reset_fail_worker_func(struct work_struct *w);
>  int intel_guc_submission_init(struct intel_guc *guc)
>  {
>  	struct intel_gt *gt = guc_to_gt(guc);
> -	int ret;
>  
>  	if (guc->submission_initialized)
>  		return 0;
>  
> -	ret = guc_lrc_desc_pool_create(guc);
> -	if (ret)
> -		return ret;
> -	/*
> -	 * Keep static analysers happy, let them know that we allocated the
> -	 * vma after testing that it didn't exist earlier.
> -	 */
> -	GEM_BUG_ON(!guc->lrc_desc_pool);
> -
>  	guc->submission_state.guc_ids_bitmap =
>  		bitmap_zalloc(NUMBER_MULTI_LRC_GUC_ID(guc), GFP_KERNEL);
>  	if (!guc->submission_state.guc_ids_bitmap)
> @@ -1844,7 +1820,6 @@ void intel_guc_submission_fini(struct intel_guc *guc)
>  		return;
>  
>  	guc_flush_destroyed_contexts(guc);
> -	guc_lrc_desc_pool_destroy(guc);
>  	i915_sched_engine_put(guc->sched_engine);
>  	bitmap_free(guc->submission_state.guc_ids_bitmap);
>  	guc->submission_initialized = false;
> @@ -2104,69 +2079,96 @@ static void unpin_guc_id(struct intel_guc *guc, struct intel_context *ce)
>  
>  static int __guc_action_register_multi_lrc(struct intel_guc *guc,
>  					   struct intel_context *ce,
> -					   u32 guc_id,
> -					   u32 offset,
> +					   struct guc_ctxt_registration_info *info,
>  					   bool loop)
>  {
>  	struct intel_context *child;
> -	u32 action[4 + MAX_ENGINE_INSTANCE];
> +	u32 action[13 + (MAX_ENGINE_INSTANCE * 2)];
>  	int len = 0;
> +	u32 next_id;
>  
>  	GEM_BUG_ON(ce->parallel.number_children > MAX_ENGINE_INSTANCE);
>  
>  	action[len++] = INTEL_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC;
> -	action[len++] = guc_id;
> +	action[len++] = info->flags;
> +	action[len++] = info->context_idx;
> +	action[len++] = info->engine_class;
> +	action[len++] = info->engine_submit_mask;
> +	action[len++] = info->wq_desc_lo;
> +	action[len++] = info->wq_desc_hi;
> +	action[len++] = info->wq_base_lo;
> +	action[len++] = info->wq_base_hi;
> +	action[len++] = info->wq_size;
>  	action[len++] = ce->parallel.number_children + 1;
> -	action[len++] = offset;
> +	action[len++] = info->hwlrca_lo;
> +	action[len++] = info->hwlrca_hi;
> +
> +	next_id = info->context_idx + 1;
>  	for_each_child(ce, child) {
> -		offset += sizeof(struct guc_lrc_desc);
> -		action[len++] = offset;
> +		GEM_BUG_ON(next_id++ != child->guc_id.id);
> +
> +		/*
> +		 * NB: GuC interface supports 64 bit LRCA even though i915/HW
> +		 * only supports 32 bit currently.
> +		 */
> +		action[len++] = lower_32_bits(child->lrc.lrca);
> +		action[len++] = upper_32_bits(child->lrc.lrca);
>  	}
>  
> +	GEM_BUG_ON(len > ARRAY_SIZE(action));
> +
>  	return guc_submission_send_busy_loop(guc, action, len, 0, loop);
>  }
>  
>  static int __guc_action_register_context(struct intel_guc *guc,
> -					 u32 guc_id,
> -					 u32 offset,
> +					 struct guc_ctxt_registration_info *info,
>  					 bool loop)
>  {
>  	u32 action[] = {
>  		INTEL_GUC_ACTION_REGISTER_CONTEXT,
> -		guc_id,
> -		offset,
> +		info->flags,
> +		info->context_idx,
> +		info->engine_class,
> +		info->engine_submit_mask,
> +		info->wq_desc_lo,
> +		info->wq_desc_hi,
> +		info->wq_base_lo,
> +		info->wq_base_hi,
> +		info->wq_size,
> +		info->hwlrca_lo,
> +		info->hwlrca_hi,
>  	};
>  
>  	return guc_submission_send_busy_loop(guc, action, ARRAY_SIZE(action),
>  					     0, loop);
>  }
>  
> -static void prepare_context_registration_info(struct intel_context *ce);
> +static void prepare_context_registration_info(struct intel_context *ce,
> +					      struct guc_ctxt_registration_info *info);
>  
>  static int register_context(struct intel_context *ce, bool loop)
>  {
> +	struct guc_ctxt_registration_info info;
>  	struct intel_guc *guc = ce_to_guc(ce);
> -	u32 offset = intel_guc_ggtt_offset(guc, guc->lrc_desc_pool) +
> -		ce->guc_id.id * sizeof(struct guc_lrc_desc);
>  	int ret;
>  
>  	GEM_BUG_ON(intel_context_is_child(ce));
>  	trace_intel_context_register(ce);
>  
> -	prepare_context_registration_info(ce);
> +	prepare_context_registration_info(ce, &info);
>  
>  	if (intel_context_is_parent(ce))
> -		ret = __guc_action_register_multi_lrc(guc, ce, ce->guc_id.id,
> -						      offset, loop);
> +		ret = __guc_action_register_multi_lrc(guc, ce, &info, loop);
>  	else
> -		ret = __guc_action_register_context(guc, ce->guc_id.id, offset,
> -						    loop);
> +		ret = __guc_action_register_context(guc, &info, loop);
>  	if (likely(!ret)) {
>  		unsigned long flags;
>  
>  		spin_lock_irqsave(&ce->guc_state.lock, flags);
>  		set_context_registered(ce);
>  		spin_unlock_irqrestore(&ce->guc_state.lock, flags);
> +
> +		guc_context_policy_init(ce, loop);
>  	}
>  
>  	return ret;
> @@ -2216,26 +2218,118 @@ static inline u32 get_children_join_value(struct intel_context *ce,
>  	return __get_parent_scratch(ce)->join[child_index].semaphore;
>  }
>  
> -static void guc_context_policy_init(struct intel_engine_cs *engine,
> -				    struct guc_lrc_desc *desc)
> +struct context_policy {
> +	u32 count;
> +	struct guc_update_context_policy h2g;
> +};
> +
> +static u32 __guc_context_policy_action_size(struct context_policy *policy)
>  {
> -	desc->policy_flags = 0;
> +	size_t bytes = sizeof(policy->h2g.header) +
> +		       (sizeof(policy->h2g.klv[0]) * policy->count);
>  
> -	if (engine->flags & I915_ENGINE_WANT_FORCED_PREEMPTION)
> -		desc->policy_flags |= CONTEXT_POLICY_FLAG_PREEMPT_TO_IDLE;
> +	return bytes / sizeof(u32);
> +}
> +
> +static void __guc_context_policy_start_klv(struct context_policy *policy, u16 guc_id)
> +{
> +	policy->h2g.header.action = INTEL_GUC_ACTION_HOST2GUC_UPDATE_CONTEXT_POLICIES;
> +	policy->h2g.header.ctx_id = guc_id;
> +	policy->count = 0;
> +}
> +
> +#define MAKE_CONTEXT_POLICY_ADD(func, id) \
> +static void __guc_context_policy_add_##func(struct context_policy *policy, u32 data) \
> +{ \
> +	GEM_BUG_ON(policy->count >= GUC_CONTEXT_POLICIES_KLV_NUM_IDS); \
> +	policy->h2g.klv[policy->count].kl = \
> +		FIELD_PREP(GUC_KLV_0_KEY, GUC_CONTEXT_POLICIES_KLV_ID_##id) | \
> +		FIELD_PREP(GUC_KLV_0_LEN, 1); \
> +	policy->h2g.klv[policy->count].value = data; \
> +	policy->count++; \
> +}
> +
> +MAKE_CONTEXT_POLICY_ADD(execution_quantum, EXECUTION_QUANTUM)
> +MAKE_CONTEXT_POLICY_ADD(preemption_timeout, PREEMPTION_TIMEOUT)
> +MAKE_CONTEXT_POLICY_ADD(priority, SCHEDULING_PRIORITY)
> +MAKE_CONTEXT_POLICY_ADD(preempt_to_idle, PREEMPT_TO_IDLE_ON_QUANTUM_EXPIRY)
> +
> +#undef MAKE_CONTEXT_POLICY_ADD
> +
> +static int __guc_context_set_context_policies(struct intel_guc *guc,
> +					      struct context_policy *policy,
> +					      bool loop)
> +{
> +	return guc_submission_send_busy_loop(guc, (u32 *)&policy->h2g,
> +					__guc_context_policy_action_size(policy),
> +					0, loop);
> +}
> +
> +static int guc_context_policy_init(struct intel_context *ce, bool loop)
> +{
> +	struct intel_engine_cs *engine = ce->engine;
> +	struct intel_guc *guc = &engine->gt->uc.guc;
> +	struct context_policy policy;
> +	u32 execution_quantum;
> +	u32 preemption_timeout;
> +	bool missing = false;
> +	unsigned long flags;
> +	int ret;
>  
>  	/* NB: For both of these, zero means disabled. */
> -	desc->execution_quantum = engine->props.timeslice_duration_ms * 1000;
> -	desc->preemption_timeout = engine->props.preempt_timeout_ms * 1000;
> +	execution_quantum = engine->props.timeslice_duration_ms * 1000;
> +	preemption_timeout = engine->props.preempt_timeout_ms * 1000;
> +
> +	__guc_context_policy_start_klv(&policy, ce->guc_id.id);
> +
> +	__guc_context_policy_add_priority(&policy, ce->guc_state.prio);
> +	__guc_context_policy_add_execution_quantum(&policy, execution_quantum);
> +	__guc_context_policy_add_preemption_timeout(&policy, preemption_timeout);
> +
> +	if (engine->flags & I915_ENGINE_WANT_FORCED_PREEMPTION)
> +		__guc_context_policy_add_preempt_to_idle(&policy, 1);
> +
> +	ret = __guc_context_set_context_policies(guc, &policy, loop);
> +	missing = ret != 0;
> +
> +	if (!missing && intel_context_is_parent(ce)) {
> +		struct intel_context *child;
> +
> +		for_each_child(ce, child) {
> +			__guc_context_policy_start_klv(&policy, child->guc_id.id);
> +
> +			if (engine->flags & I915_ENGINE_WANT_FORCED_PREEMPTION)
> +				__guc_context_policy_add_preempt_to_idle(&policy, 1);
> +
> +			child->guc_state.prio = ce->guc_state.prio;
> +			__guc_context_policy_add_priority(&policy, ce->guc_state.prio);
> +			__guc_context_policy_add_execution_quantum(&policy, execution_quantum);
> +			__guc_context_policy_add_preemption_timeout(&policy, preemption_timeout);
> +
> +			ret = __guc_context_set_context_policies(guc, &policy, loop);
> +			if (ret) {
> +				missing = true;
> +				break;
> +			}
> +		}
> +	}
> +
> +	spin_lock_irqsave(&ce->guc_state.lock, flags);
> +	if (missing)
> +		set_context_policy_required(ce);
> +	else
> +		clr_context_policy_required(ce);
> +	spin_unlock_irqrestore(&ce->guc_state.lock, flags);
> +
> +	return ret;
>  }
>  
> -static void prepare_context_registration_info(struct intel_context *ce)
> +static void prepare_context_registration_info(struct intel_context *ce,
> +					      struct guc_ctxt_registration_info *info)
>  {
>  	struct intel_engine_cs *engine = ce->engine;
>  	struct intel_guc *guc = &engine->gt->uc.guc;
>  	u32 ctx_id = ce->guc_id.id;
> -	struct guc_lrc_desc *desc;
> -	struct intel_context *child;
>  
>  	GEM_BUG_ON(!engine->mask);
>  
> @@ -2246,47 +2340,42 @@ static void prepare_context_registration_info(struct intel_context *ce)
>  	GEM_BUG_ON(i915_gem_object_is_lmem(guc->ct.vma->obj) !=
>  		   i915_gem_object_is_lmem(ce->ring->vma->obj));
>  
> -	desc = __get_lrc_desc(guc, ctx_id);
> -	desc->engine_class = engine_class_to_guc_class(engine->class);
> -	desc->engine_submit_mask = engine->logical_mask;
> -	desc->hw_context_desc = ce->lrc.lrca;
> -	desc->priority = ce->guc_state.prio;
> -	desc->context_flags = CONTEXT_REGISTRATION_FLAG_KMD;
> -	guc_context_policy_init(engine, desc);
> +	memset(info, 0, sizeof(*info));
> +	info->context_idx = ctx_id;
> +	info->engine_class = engine_class_to_guc_class(engine->class);
> +	info->engine_submit_mask = engine->logical_mask;
> +	/*
> +	 * NB: GuC interface supports 64 bit LRCA even though i915/HW
> +	 * only supports 32 bit currently.
> +	 */
> +	info->hwlrca_lo = lower_32_bits(ce->lrc.lrca);
> +	info->hwlrca_hi = upper_32_bits(ce->lrc.lrca);
> +	info->flags = CONTEXT_REGISTRATION_FLAG_KMD;
>  
>  	/*
>  	 * If context is a parent, we need to register a process descriptor
>  	 * describing a work queue and register all child contexts.
>  	 */
>  	if (intel_context_is_parent(ce)) {
> -		struct guc_process_desc *pdesc;
> +		struct guc_sched_wq_desc *wq_desc;
> +		u64 wq_desc_offset, wq_base_offset;
>  
>  		ce->parallel.guc.wqi_tail = 0;
>  		ce->parallel.guc.wqi_head = 0;
>  
> -		desc->process_desc = i915_ggtt_offset(ce->state) +
> -			__get_parent_scratch_offset(ce);
> -		desc->wq_addr = i915_ggtt_offset(ce->state) +
> -			__get_wq_offset(ce);
> -		desc->wq_size = WQ_SIZE;
> +		wq_desc_offset = i915_ggtt_offset(ce->state) +
> +				 __get_parent_scratch_offset(ce);
> +		wq_base_offset = i915_ggtt_offset(ce->state) +
> +				 __get_wq_offset(ce);
> +		info->wq_desc_lo = lower_32_bits(wq_desc_offset);
> +		info->wq_desc_hi = upper_32_bits(wq_desc_offset);
> +		info->wq_base_lo = lower_32_bits(wq_base_offset);
> +		info->wq_base_hi = upper_32_bits(wq_base_offset);
> +		info->wq_size = WQ_SIZE;
>  
> -		pdesc = __get_process_desc(ce);
> -		memset(pdesc, 0, sizeof(*(pdesc)));
> -		pdesc->stage_id = ce->guc_id.id;
> -		pdesc->wq_base_addr = desc->wq_addr;
> -		pdesc->wq_size_bytes = desc->wq_size;
> -		pdesc->wq_status = WQ_STATUS_ACTIVE;
> -
> -		for_each_child(ce, child) {
> -			desc = __get_lrc_desc(guc, child->guc_id.id);
> -
> -			desc->engine_class =
> -				engine_class_to_guc_class(engine->class);
> -			desc->hw_context_desc = child->lrc.lrca;
> -			desc->priority = ce->guc_state.prio;
> -			desc->context_flags = CONTEXT_REGISTRATION_FLAG_KMD;
> -			guc_context_policy_init(engine, desc);
> -		}
> +		wq_desc = __get_wq_desc(ce);
> +		memset(wq_desc, 0, sizeof(*wq_desc));
> +		wq_desc->wq_status = WQ_STATUS_ACTIVE;
>  
>  		clear_children_join_go_memory(ce);
>  	}
> @@ -2602,13 +2691,11 @@ static void __guc_context_set_preemption_timeout(struct intel_guc *guc,
>  						 u16 guc_id,
>  						 u32 preemption_timeout)
>  {
> -	u32 action[] = {
> -		INTEL_GUC_ACTION_SET_CONTEXT_PREEMPTION_TIMEOUT,
> -		guc_id,
> -		preemption_timeout
> -	};
> +	struct context_policy policy;
>  
> -	intel_guc_send_busy_loop(guc, action, ARRAY_SIZE(action), 0, true);
> +	__guc_context_policy_start_klv(&policy, guc_id);
> +	__guc_context_policy_add_preemption_timeout(&policy, preemption_timeout);
> +	__guc_context_set_context_policies(guc, &policy, true);
>  }
>  
>  static void guc_context_ban(struct intel_context *ce, struct i915_request *rq)
> @@ -2853,16 +2940,20 @@ static int guc_context_alloc(struct intel_context *ce)
>  	return lrc_alloc(ce, ce->engine);
>  }
>  
> +static void __guc_context_set_prio(struct intel_guc *guc,
> +				   struct intel_context *ce)
> +{
> +	struct context_policy policy;
> +
> +	__guc_context_policy_start_klv(&policy, ce->guc_id.id);
> +	__guc_context_policy_add_priority(&policy, ce->guc_state.prio);
> +	__guc_context_set_context_policies(guc, &policy, true);
> +}
> +
>  static void guc_context_set_prio(struct intel_guc *guc,
>  				 struct intel_context *ce,
>  				 u8 prio)
>  {
> -	u32 action[] = {
> -		INTEL_GUC_ACTION_SET_CONTEXT_PRIORITY,
> -		ce->guc_id.id,
> -		prio,
> -	};
> -
>  	GEM_BUG_ON(prio < GUC_CLIENT_PRIORITY_KMD_HIGH ||
>  		   prio > GUC_CLIENT_PRIORITY_NORMAL);
>  	lockdep_assert_held(&ce->guc_state.lock);
> @@ -2873,9 +2964,9 @@ static void guc_context_set_prio(struct intel_guc *guc,
>  		return;
>  	}
>  
> -	guc_submission_send_busy_loop(guc, action, ARRAY_SIZE(action), 0, true);
> -
>  	ce->guc_state.prio = prio;
> +	__guc_context_set_prio(guc, ce);
> +
>  	trace_intel_context_set_prio(ce);
>  }
>  
> @@ -4360,17 +4451,17 @@ void intel_guc_submission_print_context_info(struct intel_guc *guc,
>  		guc_log_context_priority(p, ce);
>  
>  		if (intel_context_is_parent(ce)) {
> -			struct guc_process_desc *desc = __get_process_desc(ce);
> +			struct guc_sched_wq_desc *wq_desc = __get_wq_desc(ce);
>  			struct intel_context *child;
>  
>  			drm_printf(p, "\t\tNumber children: %u\n",
>  				   ce->parallel.number_children);
>  			drm_printf(p, "\t\tWQI Head: %u\n",
> -				   READ_ONCE(desc->head));
> +				   READ_ONCE(wq_desc->head));
>  			drm_printf(p, "\t\tWQI Tail: %u\n",
> -				   READ_ONCE(desc->tail));
> +				   READ_ONCE(wq_desc->tail));
>  			drm_printf(p, "\t\tWQI Status: %u\n\n",
> -				   READ_ONCE(desc->wq_status));
> +				   READ_ONCE(wq_desc->wq_status));
>  
>  			if (ce->engine->emit_bb_start ==
>  			    emit_bb_start_parent_no_preempt_mid_batch) {
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
> index bb864655c495..cb5dd16421d0 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
> @@ -53,22 +53,22 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
>   * firmware as TGL.
>   */
>  #define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_def) \
> -	fw_def(DG2,          0, guc_def(dg2,  69, 0, 3)) \
> -	fw_def(ALDERLAKE_P,  0, guc_def(adlp, 69, 0, 3)) \
> -	fw_def(ALDERLAKE_S,  0, guc_def(tgl,  69, 0, 3)) \
> -	fw_def(DG1,          0, guc_def(dg1,  69, 0, 3)) \
> -	fw_def(ROCKETLAKE,   0, guc_def(tgl,  69, 0, 3)) \
> -	fw_def(TIGERLAKE,    0, guc_def(tgl,  69, 0, 3)) \
> -	fw_def(JASPERLAKE,   0, guc_def(ehl,  69, 0, 3)) \
> -	fw_def(ELKHARTLAKE,  0, guc_def(ehl,  69, 0, 3)) \
> -	fw_def(ICELAKE,      0, guc_def(icl,  69, 0, 3)) \
> -	fw_def(COMETLAKE,    5, guc_def(cml,  69, 0, 3)) \
> -	fw_def(COMETLAKE,    0, guc_def(kbl,  69, 0, 3)) \
> -	fw_def(COFFEELAKE,   0, guc_def(kbl,  69, 0, 3)) \
> -	fw_def(GEMINILAKE,   0, guc_def(glk,  69, 0, 3)) \
> -	fw_def(KABYLAKE,     0, guc_def(kbl,  69, 0, 3)) \
> -	fw_def(BROXTON,      0, guc_def(bxt,  69, 0, 3)) \
> -	fw_def(SKYLAKE,      0, guc_def(skl,  69, 0, 3))
> +	fw_def(DG2,          0, guc_def(dg2,  70, 1, 1)) \
> +	fw_def(ALDERLAKE_P,  0, guc_def(adlp, 70, 1, 1)) \
> +	fw_def(ALDERLAKE_S,  0, guc_def(tgl,  70, 1, 1)) \
> +	fw_def(DG1,          0, guc_def(dg1,  70, 1, 1)) \
> +	fw_def(ROCKETLAKE,   0, guc_def(tgl,  70, 1, 1)) \
> +	fw_def(TIGERLAKE,    0, guc_def(tgl,  70, 1, 1)) \
> +	fw_def(JASPERLAKE,   0, guc_def(ehl,  70, 1, 1)) \
> +	fw_def(ELKHARTLAKE,  0, guc_def(ehl,  70, 1, 1)) \
> +	fw_def(ICELAKE,      0, guc_def(icl,  70, 1, 1)) \
> +	fw_def(COMETLAKE,    5, guc_def(cml,  70, 1, 1)) \
> +	fw_def(COMETLAKE,    0, guc_def(kbl,  70, 1, 1)) \
> +	fw_def(COFFEELAKE,   0, guc_def(kbl,  70, 1, 1)) \
> +	fw_def(GEMINILAKE,   0, guc_def(glk,  70, 1, 1)) \
> +	fw_def(KABYLAKE,     0, guc_def(kbl,  70, 1, 1)) \
> +	fw_def(BROXTON,      0, guc_def(bxt,  70, 1, 1)) \
> +	fw_def(SKYLAKE,      0, guc_def(skl,  70, 1, 1))
>  
>  #define INTEL_HUC_FIRMWARE_DEFS(fw_def, huc_def) \
>  	fw_def(ALDERLAKE_P,  0, huc_def(tgl,  7, 9, 3)) \
> -- 
> 2.25.1
> 

-- 
Matt Roper
Graphics Software Engineer
VTT-OSGC Platform Enablement
Intel Corporation
(916) 356-2795


More information about the dri-devel mailing list