[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