[Intel-gfx] [PATCH 5/8] drm/i915/guc: Use GuC FW size and HW restrictions to determine WOPCM partition
Yaodong Li
yaodong.li at intel.com
Fri Mar 23 20:00:35 UTC 2018
On 03/23/2018 05:34 AM, Michał Winiarski wrote:
> We need GuC to load HuC, but it's also possible for GuC to operate on
> its own. We don't know what the size of HuC FW may be, so, not wanting
> to make any platform-specific hardcoded guesses, we assume that its size
> is 0... Which is a very bad approximation.
> This has a very unfortunate consequence - once we've booted with GuC and
> no HuC, we'll never be able to load HuC (unless we reboot, since the
> registers are locked).
> Rather than using unknown values in our computations - let's partition
> based on GuC size.
we can do this based on known GuC and HuC sizes without
any assumption on FW sizes :)
please also refer to: https://patchwork.freedesktop.org/series/40541/
> We have one HW restriction where we're using HuC size (GuC size needs to
> be roughly similar to HuC size - which may be unknown at this point),
> luckily, another HW restriction makes it very unlikely to run in any
> sort of issues in this case.
>
> Signed-off-by: Michał Winiarski <michal.winiarski at intel.com>
> Cc: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Jackie Li <yaodong.li at intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
> Cc: Michal Wajdeczko <michal.wajdeczko at intel.com>
> ---
> drivers/gpu/drm/i915/intel_wopcm.c | 60 +++++++++++++++++++++-----------------
> 1 file changed, 34 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_wopcm.c b/drivers/gpu/drm/i915/intel_wopcm.c
> index 52841d340002..295d302e97b9 100644
> --- a/drivers/gpu/drm/i915/intel_wopcm.c
> +++ b/drivers/gpu/drm/i915/intel_wopcm.c
> @@ -167,7 +167,22 @@ static int check_ctx_rsvd_fits(struct intel_wopcm *wopcm, u32 ctx_rsvd)
> return 0;
> }
>
> -static int wopcm_check_hw_restrictions(struct intel_wopcm *wopcm)
> +static inline void
> +__guc_region_grow(struct intel_wopcm *wopcm, u32 size)
> +{
> + /*
> + * We're growing guc region in the direction of lower addresses.
> + * We need to use multiples of base alignment, because it has more
> + * strict alignment rules.
> + */
> + size = DIV_ROUND_UP(size, 2);
A bit confused here. Don't we just want to push the base downward for
*size* bytes?
> + size = ALIGN(size, GUC_WOPCM_OFFSET_ALIGNMENT);
Hmm, I think we only need align it to 4K boundary.
> +
> + wopcm->guc.base -= size;
> + wopcm->guc.size += size;
> +}
> +
> +static void wopcm_adjust_for_hw_restrictions(struct intel_wopcm *wopcm)
> {
> struct drm_i915_private *i915 = wopcm_to_i915(wopcm);
> u32 huc_fw_size = intel_uc_fw_get_upload_size(&i915->huc.fw);
> @@ -177,22 +192,18 @@ static int wopcm_check_hw_restrictions(struct intel_wopcm *wopcm)
> size = gen9_size_for_dword_gap_restriction(wopcm->guc.base,
> wopcm->guc.size);
> if (size)
> - goto err;
> + __guc_region_grow(wopcm, size);
>
> size = gen9_size_for_huc_restriction(wopcm->guc.size,
> huc_fw_size);
Note that huc_fw_size might be zero in enable_guc=1 (GuC only) case.
Once the registers were locked, enable_guc=3 may still fail since
huc_fw_size
may still large enough to break the restriction we want to enforce that:
hw_fw_size + 16KB > guc_fw_size.
> if (size)
> - goto err;
> - }
> -
> - return 0;
> + __guc_region_grow(wopcm, size);
>
> -err:
> - DRM_ERROR("GuC WOPCM size %uKiB is too small. %uKiB more needed.\n",
> - wopcm->guc.size / 1024,
> - size / 1024);
> -
> - return -E2BIG;
> + GEM_BUG_ON(gen9_size_for_dword_gap_restriction(wopcm->guc.base,
> + wopcm->guc.size));
> + GEM_BUG_ON(gen9_size_for_huc_restriction(wopcm->guc.size,
> + huc_fw_size));
> + }
> }
>
> static bool wopcm_check_components_fit(struct intel_wopcm *wopcm)
> @@ -218,21 +229,16 @@ static bool wopcm_check_components_fit(struct intel_wopcm *wopcm)
> return 0;
> }
>
> -static int wopcm_guc_init(struct intel_wopcm *wopcm)
> +static int wopcm_guc_region_init(struct intel_wopcm *wopcm)
> {
> struct drm_i915_private *dev_priv = wopcm_to_i915(wopcm);
> - u32 huc_fw_size = intel_uc_fw_get_upload_size(&dev_priv->huc.fw);
> + u32 guc_fw_size = intel_uc_fw_get_upload_size(&dev_priv->guc.fw);
> u32 ctx_rsvd = context_reserved_size(dev_priv);
>
> - wopcm->guc.base = ALIGN_DOWN(huc_fw_size_in_wopcm(huc_fw_size),
> - GUC_WOPCM_OFFSET_ALIGNMENT);
> + wopcm->guc.size = guc_fw_size_in_wopcm(guc_fw_size);
>
> - wopcm->guc.size = ALIGN(wopcm->size - wopcm->guc.base - ctx_rsvd,
> - PAGE_SIZE);
> -
> - DRM_DEBUG_DRIVER("GuC WOPCM Region: [%uKiB, %uKiB)\n",
> - wopcm->guc.base / 1024,
> - (wopcm->guc.base + wopcm->guc.size) / 1024);
> + wopcm->guc.base = ALIGN_DOWN(wopcm->size - ctx_rsvd - wopcm->guc.size,
> + GUC_WOPCM_OFFSET_ALIGNMENT);
guc.size + ctx_rsvd > wopcm->size check?
>
> return 0;
> }
> @@ -255,18 +261,20 @@ int intel_wopcm_init(struct intel_wopcm *wopcm)
>
> GEM_BUG_ON(!wopcm->size);
>
> - err = wopcm_guc_init(wopcm);
> + err = wopcm_guc_region_init(wopcm);
Again, wopcm will contain invalid data on failure. But maybe we can
go with it now :)
Regards,
-Jackie
More information about the Intel-gfx
mailing list