[Intel-gfx] [PATCH v9 3/7] drm/i915/guc: Implement dynamic GuC WOPCM offset and size

Michal Wajdeczko michal.wajdeczko at intel.com
Fri Feb 9 17:24:58 UTC 2018


On Fri, 09 Feb 2018 00:03:51 +0100, Jackie Li <yaodong.li at intel.com> wrote:

> Hardware may have specific restrictions on GuC WOPCM offset and size. On
> Gen9, the value of the GuC WOPCM size register needs to be larger than  
> the
> value of GuC WOPCM offset register + a Gen9 specific offset (144KB) for
> reserved GuC WOPCM. Fail to enforce such a restriction on GuC WOPCM size
> will lead to GuC firmware execution failures. So we need add code to  
> verify
> the GuC WOPCM offset and size to avoid any GuC failures. On the other  
> hand,
> with current static GuC WOPCM offset and size values (512KB for both  
> offset
> and size), the GuC WOPCM size verification will fail on Gen9 even if it  
> can
> be fixed by lowering the GuC WOPCM offset by calculating its value based  
> on
> HuC firmware size (which is likely less than 200KB on Gen9), so that we  
> can
> have a GuC WOPCM size value which is large enough to pass the GuC WOPCM
> size check.
>
> This patch updates the reserved GuC WOPCM size for RC6 context on Gen9 to
> 24KB to strictly align with the Gen9 GuC WOPCM layout and add support to
> return CNL specific hardware reserved GuC WOPCM size. It also adds  
> support
> to verify the GuC WOPCM size aganist the Gen9 hardware restrictions.
> Meanwhile, it provides a common way to calculate GuC WOPCM offset and  
> size
> based on GuC and HuC firmware sizes for all GuC/HuC enabled platforms.
> Currently, GuC WOPCM offset is calculated based on HuC firmware size +
> reserved WOPCM size while GuC WOPCM size is set to total WOPCM size - GuC
> WOPCM offset - hardware reserved GuC WOPCM size. In this case, GuC WOPCM
> offset will be updated based on the size of HuC firmware while GuC WOPCM
> size will be set to use all the remaining WOPCM space.
>
> v2:
>  - Removed intel_wopcm_init (Ville/Sagar/Joonas)
>  - Renamed and Moved the intel_wopcm_partition into intel_guc (Sagar)
>  - Removed unnecessary function calls (Joonas)
>  - Init GuC WOPCM partition as soon as firmware fetching is completed
>
> v3:
>  - Fixed indentation issues (Chris)
>  - Removed layering violation code (Chris/Michal)
>  - Created separat files for GuC wopcm code  (Michal)
>  - Used inline function to avoid code duplication (Michal)
>
> v4:
>  - Preset the GuC WOPCM top during early GuC init (Chris)
>  - Fail intel_uc_init_hw() as soon as GuC WOPCM partitioning failed
>
> v5:
>  - Moved GuC DMA WOPCM register updating code into intel_guc_wopcm.c
>  - Took care of the locking status before writing to GuC DMA
>    Write-Once registers. (Joonas)
>
> v6:
>  - Made sure the GuC WOPCM size to be multiple of 4K (4K aligned)
>
> v8:
>  - Updated comments and fixed naming issues (Sagar/Joonas)
>  - Updated commit message to include more description about the hardware
>    restriction on GuC WOPCM size (Sagar)
>
> v9:
>  - Minor changes variable names and code comments (Sagar)
>  - Added detailed GuC WOPCM layout drawing (Sagar/Michal)
>  - Refined macro definitions to be reader friendly (Michal)
>  - Removed redundent check to valid flag (Michal)
>  - Unified first parameter for exported GuC WOPCM functions (Michal)
>  - Refined the name and parameter list of hardware restriction checking
>    functions (Michal)
>
> Cc: Michal Wajdeczko <michal.wajdeczko at intel.com>
> Cc: Sagar Arun Kamble <sagar.a.kamble at intel.com>
> Cc: Sujaritha Sundaresan <sujaritha.sundaresan at intel.com>
> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
> Cc: John Spotswood <john.a.spotswood at intel.com>
> Cc: Oscar Mateo <oscar.mateo at intel.com>
> Cc: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
> Reviewed-by: Sagar Arun Kamble <sagar.a.kamble at intel.com> (v8)
> Signed-off-by: Jackie Li <yaodong.li at intel.com>
> ---
>  drivers/gpu/drm/i915/i915_gem_context.c |   5 +-
>  drivers/gpu/drm/i915/intel_guc.c        |   5 +-
>  drivers/gpu/drm/i915/intel_guc.h        |  12 ++--
>  drivers/gpu/drm/i915/intel_guc_wopcm.c  | 115  
> +++++++++++++++++++++++++++++---
>  drivers/gpu/drm/i915/intel_guc_wopcm.h  |  85 +++++++++++++++++++++--
>  drivers/gpu/drm/i915/intel_huc.c        |   2 +-
>  drivers/gpu/drm/i915/intel_uc.c         |  11 ++-
>  drivers/gpu/drm/i915/intel_uc_fw.c      |  11 ++-
>  drivers/gpu/drm/i915/intel_uc_fw.h      |  16 +++++
>  9 files changed, 229 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_context.c  
> b/drivers/gpu/drm/i915/i915_gem_context.c
> index 3d75f48..414eab2 100644
> --- a/drivers/gpu/drm/i915/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/i915_gem_context.c
> @@ -312,12 +312,13 @@ __create_hw_context(struct drm_i915_private  
> *dev_priv,
>  	ctx->desc_template =
>  		default_desc_template(dev_priv, dev_priv->mm.aliasing_ppgtt);
> -	/* GuC requires the ring to be placed above GUC_WOPCM_TOP. If GuC is  
> not
> +	/*
> +	 * GuC requires the ring to be placed above GuC WOPCM top. If GuC is  
> not
>  	 * present or not in use we still need a small bias as ring wraparound
>  	 * at offset 0 sometimes hangs. No idea why.
>  	 */
>  	if (USES_GUC(dev_priv))
> -		ctx->ggtt_offset_bias = GUC_WOPCM_TOP;
> +		ctx->ggtt_offset_bias = dev_priv->guc.wopcm.top;
>  	else
>  		ctx->ggtt_offset_bias = I915_GTT_PAGE_SIZE;
> diff --git a/drivers/gpu/drm/i915/intel_guc.c  
> b/drivers/gpu/drm/i915/intel_guc.c
> index d9bc2a9..ecd5da2 100644
> --- a/drivers/gpu/drm/i915/intel_guc.c
> +++ b/drivers/gpu/drm/i915/intel_guc.c
> @@ -65,6 +65,7 @@ void intel_guc_init_early(struct intel_guc *guc)
>  	intel_guc_fw_init_early(guc);
>  	intel_guc_ct_init_early(&guc->ct);
>  	intel_guc_log_init_early(guc);
> +	intel_guc_wopcm_init_early(&guc->wopcm);
> 	mutex_init(&guc->send_mutex);
>  	guc->send = intel_guc_send_nop;
> @@ -478,7 +479,7 @@ int intel_guc_resume(struct drm_i915_private  
> *dev_priv)
>   * This is a wrapper to create an object for use with the GuC. In order  
> to
>   * use it inside the GuC, an object needs to be pinned lifetime, so we  
> allocate
>   * both some backing storage and a range inside the Global GTT. We must  
> pin
> - * it in the GGTT somewhere other than than [0, GUC_WOPCM_TOP) because  
> that
> + * it in the GGTT somewhere other than than [0, GuC WOPCM top) because  
> that
>   * range is reserved inside GuC.
>   *
>   * Return:	A i915_vma if successful, otherwise an ERR_PTR.
> @@ -499,7 +500,7 @@ struct i915_vma *intel_guc_allocate_vma(struct  
> intel_guc *guc, u32 size)
>  		goto err;
> 	ret = i915_vma_pin(vma, 0, PAGE_SIZE,
> -			   PIN_GLOBAL | PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
> +			   PIN_GLOBAL | PIN_OFFSET_BIAS | guc->wopcm.top);
>  	if (ret) {
>  		vma = ERR_PTR(ret);
>  		goto err;
> diff --git a/drivers/gpu/drm/i915/intel_guc.h  
> b/drivers/gpu/drm/i915/intel_guc.h
> index 50be6de..06f315e 100644
> --- a/drivers/gpu/drm/i915/intel_guc.h
> +++ b/drivers/gpu/drm/i915/intel_guc.h
> @@ -49,6 +49,7 @@ struct intel_guc {
>  	struct intel_uc_fw fw;
>  	struct intel_guc_log log;
>  	struct intel_guc_ct ct;
> +	struct intel_guc_wopcm wopcm;
> 	/* Log snapshot if GuC errors during load */
>  	struct drm_i915_gem_object *load_err_log;
> @@ -109,10 +110,10 @@ static inline void intel_guc_notify(struct  
> intel_guc *guc)
>   * @guc: intel guc.
>   * @vma: i915 graphics virtual memory area.
>   *
> - * GuC does not allow any gfx GGTT address that falls into range [0,  
> WOPCM_TOP),
> - * which is reserved for Boot ROM, SRAM and WOPCM. Currently this top  
> address is
> - * 512K. In order to exclude 0-512K address space from GGTT, all gfx  
> objects
> - * used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM.
> + * GuC does not allow any gfx GGTT address that falls into range
> + * [0, GuC WOPCM top), which is reserved for Boot ROM, SRAM and WOPCM.
> + * All gfx objects used by GuC is pinned with PIN_OFFSET_BIAS along with
> + * top of WOPCM.
>   *
>   * Return: GGTT offset that meets the GuC gfx address requirement.
>   */
> @@ -121,7 +122,8 @@ static inline u32 intel_guc_ggtt_offset(struct  
> intel_guc *guc,
>  {
>  	u32 offset = i915_ggtt_offset(vma);
> -	GEM_BUG_ON(offset < GUC_WOPCM_TOP);
> +	GEM_BUG_ON(!guc->wopcm.valid);
> +	GEM_BUG_ON(offset < guc->wopcm.top);
>  	GEM_BUG_ON(range_overflows_t(u64, offset, vma->size, GUC_GGTT_TOP));
> 	return offset;
> diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.c  
> b/drivers/gpu/drm/i915/intel_guc_wopcm.c
> index c3d54f8..8b2ce49 100644
> --- a/drivers/gpu/drm/i915/intel_guc_wopcm.c
> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
> @@ -27,22 +27,115 @@
>  #include "intel_guc_wopcm.h"
>  #include "i915_drv.h"
> +static inline u32 guc_wopcm_context_reserved_size(struct intel_guc *guc)
> +{
> +	struct drm_i915_private *i915 = guc_to_i915(guc);
> +
> +	if (IS_GEN9_LP(i915))
> +		return BXT_GUC_WOPCM_RC6_CTX_RESERVED;
> +
> +	return 0;
> +}
> +
> +static inline int gen9_guc_wopcm_size_check(struct intel_guc_wopcm  
> *guc_wopcm)
> +{
> +	u32 guc_wopcm_start;
> +	u32 delta;
> +
> +	/*
> +	 * GuC WOPCM size is at least a dword larger than the offset from WOPCM
> +	 * base (GuC WOPCM offset from WOPCM base + GEN9_GUC_WOPCM_OFFSET) due
> +	 * to hardware limitation on Gen9.
> +	 */
> +	guc_wopcm_start = guc_wopcm->offset + GEN9_GUC_WOPCM_OFFSET;
> +	if (unlikely(guc_wopcm_start > guc_wopcm->size))
> +		return -E2BIG;
> +
> +	delta = guc_wopcm->size - guc_wopcm_start;
> +	if (unlikely(delta < sizeof(u32)))
> +		return -E2BIG;
> +
> +	return 0;
> +}
> +
> +static inline int guc_wopcm_size_check(struct intel_guc *guc)
> +{
> +	struct drm_i915_private *i915 = guc_to_i915(guc);
> +	struct intel_guc_wopcm *guc_wopcm = &guc->wopcm;
> +
> +	if (IS_GEN9(i915))
> +		return gen9_guc_wopcm_size_check(guc_wopcm);
> +
> +	return 0;
> +}
> +
>  /**
> - * intel_guc_wopcm_size() - Get the size of GuC WOPCM.
> - * @guc: intel guc.
> + * intel_guc_wopcm_init() - Initialize the GuC WOPCM.
> + * @guc_wopcm: intel_guc_wopcm..

Please use better description, maybe "[pointer to] GuC WOPCM"
And remove redundant trailing dot.

> + * @guc_fw_size: size of GuC firmware.
> + * @huc_fw_size: size of HuC firmware.
>   *
> - * Get the platform specific GuC WOPCM size.
> + * Calculate the GuC WOPCM offset and size based on GuC and HuC  
> firmware sizes.
> + * This function will set the GuC WOPCM size to the size of maximum  
> WOPCM
> + * available for GuC. This function will also enforce platform dependent
> + * hardware restrictions on GuC WOPCM offset and size. It will fail the  
> GuC
> + * WOPCM init if any of these checks were failed, so that the following  
> GuC
> + * firmware uploading would be aborted.
>   *
> - * Return: size of the GuC WOPCM.
> + * Return: 0 on success, non-zero error code on failure.
>   */
> -u32 intel_guc_wopcm_size(struct intel_guc *guc)
> +int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32  
> guc_fw_size,
> +			 u32 huc_fw_size)
>  {
> -	struct drm_i915_private *i915 = guc_to_i915(guc);
> -	u32 size = GUC_WOPCM_TOP;
> +	struct intel_guc *guc =
> +		container_of(guc_wopcm, struct intel_guc, wopcm);

If you define this as "wopcm_to_guc" inline helper, then maybe
all your functions could take "wopcm" as first parameter?

> +	u32 reserved = guc_wopcm_context_reserved_size(guc);
> +	u32 offset, size, top;
> +	int err;
> -	/* On BXT, the top of WOPCM is reserved for RC6 context */
> -	if (IS_GEN9_LP(i915))
> -		size -= BXT_GUC_WOPCM_RC6_RESERVED;
> +	if (!guc_fw_size)
> +		return -EINVAL;

As there are many reasons to fail, maybe it would be good idea to
add at least DRM_DEBUG_DRIVER to each failing condition?

> +
> +	if (reserved >= WOPCM_DEFAULT_SIZE)
> +		return -E2BIG;

Do we really need to check this every time in runtime?
I think we can enforce this as GEM_BUG_ON here or in
guc_wopcm_context_reserved_size() function.

> +
> +	offset = huc_fw_size + WOPCM_RESERVED_SIZE;
> +	if (offset >= WOPCM_DEFAULT_SIZE)
> +		return -E2BIG;
> +
> +	/* Hardware requires GuC WOPCM offset to be 16K aligned. */
> +	offset = ALIGN(offset, GUC_WOPCM_OFFSET_ALIGNMENT);
> +	if ((offset + reserved) >= WOPCM_DEFAULT_SIZE)
> +		return -E2BIG;
> +
> +	top = WOPCM_DEFAULT_SIZE - offset;
> +	size = top - reserved;
> +
> +	/* GuC WOPCM size must be multiple of 4K pages */
> +	size &= PAGE_MASK;

Hmm, this will work only in CONFIG_IA64_PAGE_SIZE_4KB, is it ok?

> +
> +	/*
> +	 * GuC firmware size needs to be less than or equal to the size of the
> +	 * available GuC WOPCM (total available GuC WOPCM size - reserved  
> size).
> +	 * Need extra 8K stack for GuC firmware.
> +	 */
> +	reserved = GUC_WOPCM_RESERVED + GUC_WOPCM_STACK_RESERVED;
> +	if ((guc_fw_size + reserved) > size)
> +		return -E2BIG;
> +
> +	guc->wopcm.offset = offset;
> +	guc->wopcm.size = size;
> +	guc->wopcm.top = top;
> +
> +	/* Check platform specific restrictions */
> +	err = guc_wopcm_size_check(guc);

maybe "guc_wopcm_check_size(guc_wopcm)"

> +	if (err)
> +		return err;
> +
> +	guc->wopcm.valid = 1;
> +
> +	DRM_DEBUG_DRIVER("GuC WOPCM offset %dKB, size %dKB, top %dKB\n",
> +			 offset >> 10, size >> 10, top >> 10);
> -	return size;
> +	return 0;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.h  
> b/drivers/gpu/drm/i915/intel_guc_wopcm.h
> index 7323604..3af7ca9 100644
> --- a/drivers/gpu/drm/i915/intel_guc_wopcm.h
> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.h
> @@ -31,15 +31,86 @@
> struct intel_guc;
> -/* 512KB static offset from WOPCM base. */
> -#define GUC_WOPCM_OFFSET_VALUE		(512 << 10)
>  /*
> - * 512KB static GuC WOPCM size from GUC_WOPCM_OFFSET_VALUE to the end  
> of GuC
> - * WOPCM. GuC addresses below GUC_WOPCM_TOP don't map through the GTT.
> + * The layout of the WOPCM will be determined by GuC WOPCM size and  
> offset
> + * registers settings. Currently, GuC WOPCM code calculates the GuC  
> WOPCM offset
> + * and size values based on a layout as shown below:
> + *
> + *   +=====+==>+====================+<== GuC WOPCM top
> + *   ^     ^   |  HW contexts RSVD  |
> + *   |     |   +--------------------+<== GuC WOPCM size
> + *   |     |   |                    |
> + *   |    GuC  |                    |
> + *   |   WOPCM +--------------------+<== (Platform specific size)
> + *   |     |   |    GuC FW RSVD     |
> + * WOPCM   |   +------------------- +<== (16KB)
> + *   |     v   |   RSVD GUC WOPCM   |

Please be consistent in naming: Guc vs. GUC

> + *   |     +==>+====================+<== GuC WOPCM offset
> + *   |         |     RSVD WOPCM     |
> + *   |         +------------------- +
> + *   v         |      HuC FW        |
> + *   +========>+====================+<== WOPCM Base
> + *
> + * GuC accessible WOPCM starts at GuC WOPCM offset and ends at GuC  
> WOPCM size.
> + * The top part of the GuC WOPCM is reserved for hardware contexts  
> (e.g. RC6
> + * context). We need to keep tracking the GuC WOPCM top since hardware  
> requires
> + * the GGTT offset of a GuC accessible GEM buffer to be larger than the  
> value of
> + * GuC WOPCM top. The values of GuC WOPCM size and top should be set to  
> the
> + * length from GuC WOPCM offset in bytes.
> + */
> +
> +/* Default WOPCM size 1MB. */
> +#define WOPCM_DEFAULT_SIZE		(0x1 << 20)

(1 << 20) or (1024 * 1024)

> +/* The initial 16KB WOPCM (RSVD WOPCM) is reserved. */
> +#define WOPCM_RESERVED_SIZE		(16 << 10)
> +
> +/* GUC WOPCM offset needs to be 16KB aligned. */
> +#define GUC_WOPCM_OFFSET_ALIGNMENT	(16 << 10)
> +/* 16KB reserved at the beginning of GuC WOPCM. */
> +#define GUC_WOPCM_RESERVED		(16 << 10)
> +/* 8KB from GUC_WOPCM_RESERVED is reserved for GuC stack. */
> +#define GUC_WOPCM_STACK_RESERVED	(8 << 10)
> +/* 24KB at the end of GuC WOPCM is reserved for RC6 CTX on BXT. */
> +#define BXT_GUC_WOPCM_RC6_CTX_RESERVED	(24 << 10)
> +
> +/*
> + * GuC WOPCM starts at 144KB (GUC_WOPCM_RESERVED + 128KB reserved for  
> GuC
> + * firmware loading) from GuC WOPCM offset on BXT.
> + */
> +#define GEN9_GUC_WOPCM_OFFSET		(144 << 10)

Other BXT specific macro (BXT_GUC_WOPCM_RC6_CTX_RESERVED) was
defined with BXT_ prefix ... can we use common prefix?

> +
> +/**
> + * intel_guc_wopcm - GuC WOPCM related settings.
> + * @offset: GuC WOPCM offset from the WOPCM base.
> + * @size: size of GuC WOPCM for GuC firmware.
> + * @top: start of the non-GuC WOPCM memory.
> + * @valid: whether this structure contains valid (1-valid, 0-invalid)  
> info.
> + *
> + * We simply use this structure to track the GuC use of WOPCM. The  
> layout of
> + * WOPCM would be defined by writing to GuC WOPCM offset and size  
> registers.
> + */
> +struct intel_guc_wopcm {
> +	u32 offset;
> +	u32 size;
> +	u32 top;
> +	u32 valid;
> +};
> +
> +/**
> + * intel_guc_wopcm_init_early() - Early initialization of the GuC WOPCM.
> + * @guc_wopcm: intel_guc_wopcm.
> + *
> + * Setup the GuC WOPCM top to the top of the overall WOPCM. This will  
> guarantee
> + * that the allocation of the GuC accessible objects won't fall into  
> WOPCM when
> + * GuC partition isn't present.
> + *
>   */
> -#define GUC_WOPCM_TOP			(512 << 10)
> -#define BXT_GUC_WOPCM_RC6_RESERVED	(64 << 10)
> +static inline void intel_guc_wopcm_init_early(struct intel_guc_wopcm  
> *guc_wopcm)
> +{
> +	guc_wopcm->top = WOPCM_DEFAULT_SIZE;
> +}
> -u32 intel_guc_wopcm_size(struct intel_guc *guc);
> +int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32  
> guc_size,
> +			 u32 huc_size);
> #endif
> diff --git a/drivers/gpu/drm/i915/intel_huc.c  
> b/drivers/gpu/drm/i915/intel_huc.c
> index aed9c1c..dc6a6c6 100644
> --- a/drivers/gpu/drm/i915/intel_huc.c
> +++ b/drivers/gpu/drm/i915/intel_huc.c
> @@ -206,7 +206,7 @@ int intel_huc_auth(struct intel_huc *huc)
>  		return -ENOEXEC;
> 	vma = i915_gem_object_ggtt_pin(huc->fw.obj, NULL, 0, 0,
> -				PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
> +				PIN_OFFSET_BIAS | guc->wopcm.top);
>  	if (IS_ERR(vma)) {
>  		ret = PTR_ERR(vma);
>  		DRM_ERROR("HuC: Failed to pin huc fw object %d\n", ret);
> diff --git a/drivers/gpu/drm/i915/intel_uc.c  
> b/drivers/gpu/drm/i915/intel_uc.c
> index 1b2831b..c842f36 100644
> --- a/drivers/gpu/drm/i915/intel_uc.c
> +++ b/drivers/gpu/drm/i915/intel_uc.c
> @@ -283,6 +283,9 @@ void intel_uc_fini_misc(struct drm_i915_private  
> *dev_priv)
>  int intel_uc_init(struct drm_i915_private *dev_priv)
>  {
>  	struct intel_guc *guc = &dev_priv->guc;
> +	struct intel_huc *huc = &dev_priv->huc;
> +	u32 guc_fw_size = intel_uc_fw_get_size(&guc->fw);
> +	u32 huc_fw_size = intel_uc_fw_get_size(&huc->fw);
>  	int ret;
> 	if (!USES_GUC(dev_priv))
> @@ -291,6 +294,10 @@ int intel_uc_init(struct drm_i915_private *dev_priv)
>  	if (!HAS_GUC(dev_priv))
>  		return -ENODEV;
> +	ret = intel_guc_wopcm_init(&guc->wopcm, guc_fw_size, huc_fw_size);
> +	if (ret)
> +		return ret;
> +
>  	ret = intel_guc_init(guc);
>  	if (ret)
>  		return ret;
> @@ -340,9 +347,9 @@ int intel_uc_init_hw(struct drm_i915_private  
> *dev_priv)
>  	gen9_reset_guc_interrupts(dev_priv);
> 	/* init WOPCM */
> -	I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(guc));
> +	I915_WRITE(GUC_WOPCM_SIZE, guc->wopcm.size);
>  	I915_WRITE(DMA_GUC_WOPCM_OFFSET,
> -		   GUC_WOPCM_OFFSET_VALUE | HUC_LOADING_AGENT_GUC);
> +		   guc->wopcm.offset | HUC_LOADING_AGENT_GUC);
> 	/* WaEnableuKernelHeaderValidFix:skl */
>  	/* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
> diff --git a/drivers/gpu/drm/i915/intel_uc_fw.c  
> b/drivers/gpu/drm/i915/intel_uc_fw.c
> index 24945cf..791263a 100644
> --- a/drivers/gpu/drm/i915/intel_uc_fw.c
> +++ b/drivers/gpu/drm/i915/intel_uc_fw.c
> @@ -95,9 +95,13 @@ void intel_uc_fw_fetch(struct drm_i915_private  
> *dev_priv,
>  	uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size;
>  	uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
> -	/* Header and uCode will be loaded to WOPCM */
> +	/*
> +	 * Header and uCode will be loaded to WOPCM
> +	 * Only check the size against the overall available WOPCM here. Will
> +	 * continue to check the size during WOPCM partition calculation.
> +	 */
>  	size = uc_fw->header_size + uc_fw->ucode_size;
> -	if (size > intel_guc_wopcm_size(&dev_priv->guc)) {
> +	if (size > WOPCM_DEFAULT_SIZE) {
>  		DRM_WARN("%s: Firmware is too large to fit in WOPCM\n",
>  			 intel_uc_fw_type_repr(uc_fw->type));
>  		err = -E2BIG;
> @@ -207,6 +211,7 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,
>  		       int (*xfer)(struct intel_uc_fw *uc_fw,
>  				   struct i915_vma *vma))
>  {
> +	struct drm_i915_private *i915 = to_i915(uc_fw->obj->base.dev);
>  	struct i915_vma *vma;
>  	int err;
> @@ -230,7 +235,7 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,
>  	}
> 	vma = i915_gem_object_ggtt_pin(uc_fw->obj, NULL, 0, 0,
> -				       PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
> +				       PIN_OFFSET_BIAS | i915->guc.wopcm.top);
>  	if (IS_ERR(vma)) {
>  		err = PTR_ERR(vma);
>  		DRM_DEBUG_DRIVER("%s fw ggtt-pin err=%d\n",
> diff --git a/drivers/gpu/drm/i915/intel_uc_fw.h  
> b/drivers/gpu/drm/i915/intel_uc_fw.h
> index d5fd460..298d475 100644
> --- a/drivers/gpu/drm/i915/intel_uc_fw.h
> +++ b/drivers/gpu/drm/i915/intel_uc_fw.h
> @@ -115,6 +115,22 @@ static inline bool intel_uc_fw_is_selected(struct  
> intel_uc_fw *uc_fw)
>  	return uc_fw->path != NULL;
>  }
> +/**
> + * intel_uc_fw_get_size() - Get the size of the firmware.
> + * @uc_fw: intel_uc_fw structure.
> + *
> + * Get the size of the firmware that will be placed in WOPCM.
> + *
> + * Return: Zero on invalid firmware status. actual size on success.

Return: Size of the firmware, or zero on firmware fetch failure.

> + */
> +static inline u32 intel_uc_fw_get_size(struct intel_uc_fw *uc_fw)
> +{
> +	if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
> +		return 0;
> +
> +	return uc_fw->header_size + uc_fw->ucode_size;
> +}
> +
>  void intel_uc_fw_fetch(struct drm_i915_private *dev_priv,
>  		       struct intel_uc_fw *uc_fw);
>  int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,


More information about the Intel-gfx mailing list