[PATCH v2 3/3] drm/i915/guc: Use GuC submission API version number

Ceraolo Spurio, Daniele daniele.ceraolospurio at intel.com
Tue Nov 29 19:19:02 UTC 2022



On 11/23/2022 2:31 PM, John.C.Harrison at Intel.com wrote:
> From: John Harrison <John.C.Harrison at Intel.com>
>
> The GuC firmware includes an extra version number to specify the
> submission API level. So use that rather than the main firmware
> version number for submission related checks.
>
> Also, while it is guaranteed that GuC version number components are
> only 8-bits in size, other firmwares do not have that restriction. So
> stop making assumptions about them generically fitting in a u16
> individually, or in a u32 as a combined 8.8.8.
>
> Signed-off-by: John Harrison <John.C.Harrison at Intel.com>
> ---
>   drivers/gpu/drm/i915/gt/uc/intel_guc.h        |  11 ++
>   .../gpu/drm/i915/gt/uc/intel_guc_submission.c |  15 ++-
>   drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c      | 124 ++++++++++++++++--
>   drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h      |  10 +-
>   drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h  |   3 +-
>   5 files changed, 137 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> index 1bb3f98292866..bb4dfe707a7d0 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> @@ -158,6 +158,9 @@ struct intel_guc {
>   	bool submission_selected;
>   	/** @submission_initialized: tracks whether GuC submission has been initialised */
>   	bool submission_initialized;
> +	/** @submission_version: Submission API version of the currently loaded firmware */
> +	struct intel_uc_fw_ver submission_version;
> +
>   	/**
>   	 * @rc_supported: tracks whether we support GuC rc on the current platform
>   	 */
> @@ -268,6 +271,14 @@ struct intel_guc {
>   #endif
>   };
>   
> +/*
> + * GuC version number components are only 8-bit, so converting to a 32bit 8.8.8
> + * integer works.
> + */
> +#define MAKE_GUC_VER(maj, min, pat)	(((maj) << 16) | ((min) << 8) | (pat))
> +#define MAKE_GUC_VER_STRUCT(ver)	MAKE_GUC_VER((ver).major, (ver).minor, (ver).patch)
> +#define GUC_SUBMIT_VER(guc)		MAKE_GUC_VER_STRUCT((guc)->submission_version)
> +
>   static inline struct intel_guc *log_to_guc(struct intel_guc_log *log)
>   {
>   	return container_of(log, struct intel_guc, log);
> 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 0a42f1807f52c..53f7f599cde3a 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
> @@ -1890,7 +1890,7 @@ int intel_guc_submission_init(struct intel_guc *guc)
>   	if (guc->submission_initialized)
>   		return 0;
>   
> -	if (GET_UC_VER(guc) < MAKE_UC_VER(70, 0, 0)) {
> +	if (GUC_SUBMIT_VER(guc) < MAKE_GUC_VER(1, 0, 0)) {
>   		ret = guc_lrc_desc_pool_create_v69(guc);
>   		if (ret)
>   			return ret;
> @@ -2330,7 +2330,7 @@ static int register_context(struct intel_context *ce, bool loop)
>   	GEM_BUG_ON(intel_context_is_child(ce));
>   	trace_intel_context_register(ce);
>   
> -	if (GET_UC_VER(guc) >= MAKE_UC_VER(70, 0, 0))
> +	if (GUC_SUBMIT_VER(guc) >= MAKE_GUC_VER(1, 0, 0))
>   		ret = register_context_v70(guc, ce, loop);
>   	else
>   		ret = register_context_v69(guc, ce, loop);
> @@ -2342,7 +2342,7 @@ static int register_context(struct intel_context *ce, bool loop)
>   		set_context_registered(ce);
>   		spin_unlock_irqrestore(&ce->guc_state.lock, flags);
>   
> -		if (GET_UC_VER(guc) >= MAKE_UC_VER(70, 0, 0))
> +		if (GUC_SUBMIT_VER(guc) >= MAKE_GUC_VER(1, 0, 0))
>   			guc_context_policy_init_v70(ce, loop);
>   	}
>   
> @@ -2956,7 +2956,7 @@ static void __guc_context_set_preemption_timeout(struct intel_guc *guc,
>   						 u16 guc_id,
>   						 u32 preemption_timeout)
>   {
> -	if (GET_UC_VER(guc) >= MAKE_UC_VER(70, 0, 0)) {
> +	if (GUC_SUBMIT_VER(guc) >= MAKE_GUC_VER(1, 0, 0)) {
>   		struct context_policy policy;
>   
>   		__guc_context_policy_start_klv(&policy, guc_id);
> @@ -3283,7 +3283,7 @@ static int guc_context_alloc(struct intel_context *ce)
>   static void __guc_context_set_prio(struct intel_guc *guc,
>   				   struct intel_context *ce)
>   {
> -	if (GET_UC_VER(guc) >= MAKE_UC_VER(70, 0, 0)) {
> +	if (GUC_SUBMIT_VER(guc) >= MAKE_GUC_VER(1, 0, 0)) {
>   		struct context_policy policy;
>   
>   		__guc_context_policy_start_klv(&policy, ce->guc_id.id);
> @@ -4366,7 +4366,7 @@ static int guc_init_global_schedule_policy(struct intel_guc *guc)
>   	intel_wakeref_t wakeref;
>   	int ret = 0;
>   
> -	if (GET_UC_VER(guc) < MAKE_UC_VER(70, 3, 0))
> +	if (GUC_SUBMIT_VER(guc) < MAKE_GUC_VER(1, 1, 0))
>   		return 0;
>   
>   	__guc_scheduling_policy_start_klv(&policy);
> @@ -4905,6 +4905,9 @@ void intel_guc_submission_print_info(struct intel_guc *guc,
>   	if (!sched_engine)
>   		return;
>   
> +	drm_printf(p, "GuC Submission API Version: %d.%d.%d\n",
> +		   guc->submission_version.major, guc->submission_version.minor,
> +		   guc->submission_version.patch);
>   	drm_printf(p, "GuC Number Outstanding Submission G2H: %u\n",
>   		   atomic_read(&guc->outstanding_submission_g2h));
>   	drm_printf(p, "GuC tasklet count: %u\n",
> 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 5e2ee1ac89514..7d2349647b593 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
> @@ -478,6 +478,62 @@ static int check_gsc_manifest(const struct firmware *fw,
>   	return 0;
>   }
>   
> +static void uc_unpack_css_version(struct intel_uc_fw_ver *ver, u32 css_value)
> +{
> +	/* Get version numbers from the CSS header */
> +	ver->major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR, css_value);
> +	ver->minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR, css_value);
> +	ver->patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH, css_value);
> +}
> +
> +static void guc_read_css_info(struct intel_uc_fw *uc_fw, struct uc_css_header *css)
> +{
> +	struct intel_guc *guc = container_of(uc_fw, struct intel_guc, fw);
> +
> +	/*
> +	 * The GuC firmware includes an extra version number to specify the
> +	 * submission API level. This allows submission code to work with
> +	 * multiple GuC versions without having to know the absolute firmware
> +	 * version number (there are likely to be multiple firmware releases
> +	 * which all support the same submission API level).
> +	 *
> +	 * Note that the spec for the CSS header defines this version number
> +	 * as 'vf_version' as it was originally intended for virtualisation.
> +	 * However, it is applicable to native submission as well.
> +	 *
> +	 * Unfortunately, due to an oversight, this version number was only
> +	 * exposed in the CSS header from v70.6.0.
> +	 */
> +	if (uc_fw->file_selected.ver.major >= 70) {
> +		if (uc_fw->file_selected.ver.minor >= 6) {
> +			/* v70.6.0 adds CSS header support */
> +			uc_unpack_css_version(&guc->submission_version, css->vf_version);
> +		} else if (uc_fw->file_selected.ver.minor >= 3) {
> +			/* v70.3.0 introduced v1.1.0 */
> +			guc->submission_version.major = 1;
> +			guc->submission_version.minor = 1;
> +			guc->submission_version.patch = 0;
> +		} else {
> +			/* v70.0.0 introduced v1.0.0 */
> +			guc->submission_version.major = 1;
> +			guc->submission_version.minor = 0;
> +			guc->submission_version.patch = 0;
> +		}
> +	} else if (uc_fw->file_selected.ver.major >= 69) {
> +		/* v69.0.0 introduced v0.10.0 */
> +		guc->submission_version.major = 0;
> +		guc->submission_version.minor = 10;
> +		guc->submission_version.patch = 0;
> +	} else {
> +		/* Prior versions were v0.1.0 */
> +		guc->submission_version.major = 0;
> +		guc->submission_version.minor = 1;
> +		guc->submission_version.patch = 0;
> +	}
> +
> +	uc_fw->private_data_size = css->private_data_size;
> +}
> +
>   static int check_ccs_header(struct intel_gt *gt,
>   			    const struct firmware *fw,
>   			    struct intel_uc_fw *uc_fw)
> @@ -531,20 +587,50 @@ static int check_ccs_header(struct intel_gt *gt,
>   		return -E2BIG;
>   	}
>   
> -	/* Get version numbers from the CSS header */
> -	uc_fw->file_selected.ver.major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
> -						   css->sw_version);
> -	uc_fw->file_selected.ver.minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR,
> -						   css->sw_version);
> -	uc_fw->file_selected.ver.patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH,
> -						   css->sw_version);
> +	uc_unpack_css_version(&uc_fw->file_selected.ver, css->sw_version);
>   
>   	if (uc_fw->type == INTEL_UC_FW_TYPE_GUC)
> -		uc_fw->private_data_size = css->private_data_size;
> +		guc_read_css_info(uc_fw, css);
>   
>   	return 0;
>   }
>   
> +static bool is_ver_8bit(struct intel_uc_fw_ver *ver)
> +{
> +	return ver->major < 0xFF && ver->minor < 0xFF && ver->patch < 0xFF;
> +}
> +
> +static bool gyc_check_version_range(struct intel_uc_fw *uc_fw)

typo gyc. With this fixed:

Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>

Daniele

> +{
> +	struct intel_guc *guc = container_of(uc_fw, struct intel_guc, fw);
> +
> +	/*
> +	 * GuC version number components are defined as being 8-bits.
> +	 * The submission code relies on this to optimise version comparison
> +	 * tests. So enforce the restriction here.
> +	 */
> +
> +	if (!is_ver_8bit(&uc_fw->file_selected.ver)) {
> +		drm_warn(&__uc_fw_to_gt(uc_fw)->i915->drm, "%s firmware: invalid file version: 0x%02X:%02X:%02X\n",
> +			 intel_uc_fw_type_repr(uc_fw->type),
> +			 uc_fw->file_selected.ver.major,
> +			 uc_fw->file_selected.ver.minor,
> +			 uc_fw->file_selected.ver.patch);
> +		return false;
> +	}
> +
> +	if (!is_ver_8bit(&guc->submission_version)) {
> +		drm_warn(&__uc_fw_to_gt(uc_fw)->i915->drm, "%s firmware: invalid submit version: 0x%02X:%02X:%02X\n",
> +			 intel_uc_fw_type_repr(uc_fw->type),
> +			 guc->submission_version.major,
> +			 guc->submission_version.minor,
> +			 guc->submission_version.patch);
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
>   /**
>    * intel_uc_fw_fetch - fetch uC firmware
>    * @uc_fw: uC firmware
> @@ -621,6 +707,9 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
>   	if (err)
>   		goto fail;
>   
> +	if (uc_fw->type == INTEL_UC_FW_TYPE_GUC && !gyc_check_version_range(uc_fw))
> +		goto fail;
> +
>   	if (uc_fw->file_wanted.ver.major) {
>   		/* Check the file's major version was as it claimed */
>   		if (uc_fw->file_selected.ver.major != uc_fw->file_wanted.ver.major) {
> @@ -1054,7 +1143,7 @@ size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len)
>    */
>   void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p)
>   {
> -	u32 ver_sel, ver_want;
> +	bool got_wanted;
>   
>   	drm_printf(p, "%s firmware: %s\n",
>   		   intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path);
> @@ -1063,9 +1152,20 @@ void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p)
>   			   intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_wanted.path);
>   	drm_printf(p, "\tstatus: %s\n",
>   		   intel_uc_fw_status_repr(uc_fw->status));
> -	ver_sel = MAKE_UC_VER_STRUCT(uc_fw->file_selected.ver);
> -	ver_want = MAKE_UC_VER_STRUCT(uc_fw->file_wanted.ver);
> -	if (ver_sel < ver_want)
> +
> +	if (uc_fw->file_selected.ver.major < uc_fw->file_wanted.ver.major)
> +		got_wanted = false;
> +	else if ((uc_fw->file_selected.ver.major == uc_fw->file_wanted.ver.major) &&
> +		 (uc_fw->file_selected.ver.minor < uc_fw->file_wanted.ver.minor))
> +		got_wanted = false;
> +	else if ((uc_fw->file_selected.ver.major == uc_fw->file_wanted.ver.major) &&
> +		 (uc_fw->file_selected.ver.minor == uc_fw->file_wanted.ver.minor) &&
> +		 (uc_fw->file_selected.ver.patch < uc_fw->file_wanted.ver.patch))
> +		got_wanted = false;
> +	else
> +		got_wanted = true;
> +
> +	if (!got_wanted)
>   		drm_printf(p, "\tversion: wanted %u.%u.%u, found %u.%u.%u\n",
>   			   uc_fw->file_wanted.ver.major,
>   			   uc_fw->file_wanted.ver.minor,
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
> index 6501d6f1fbdff..3ab87c54a3987 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
> @@ -66,9 +66,9 @@ enum intel_uc_fw_type {
>   #define INTEL_UC_FW_NUM_TYPES 2
>   
>   struct intel_uc_fw_ver {
> -	u16 major;
> -	u16 minor;
> -	u16 patch;
> +	u32 major;
> +	u32 minor;
> +	u32 patch;
>   };
>   
>   /*
> @@ -114,10 +114,6 @@ struct intel_uc_fw {
>   	bool loaded_via_gsc;
>   };
>   
> -#define MAKE_UC_VER(maj, min, pat)	((pat) | ((min) << 8) | ((maj) << 16))
> -#define MAKE_UC_VER_STRUCT(ver)		MAKE_UC_VER((ver).major, (ver).minor, (ver).patch)
> -#define GET_UC_VER(uc)			(MAKE_UC_VER_STRUCT((uc)->fw.file_selected.ver))
> -
>   /*
>    * When we load the uC binaries, we pin them in a reserved section at the top of
>    * the GGTT, which is ~18 MBs. On multi-GT systems where the GTs share the GGTT,
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h
> index 7a411178bdbf2..646fa8aa6cf19 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h
> @@ -74,7 +74,8 @@ struct uc_css_header {
>   #define CSS_SW_VERSION_UC_MAJOR		(0xFF << 16)
>   #define CSS_SW_VERSION_UC_MINOR		(0xFF << 8)
>   #define CSS_SW_VERSION_UC_PATCH		(0xFF << 0)
> -	u32 reserved0[13];
> +	u32 vf_version;
> +	u32 reserved0[12];
>   	union {
>   		u32 private_data_size; /* only applies to GuC */
>   		u32 reserved1;



More information about the dri-devel mailing list