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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Quoting Jackie Li (2018-02-09 01:03:51)
> 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@xxxxxxxxx>
> Cc: Sagar Arun Kamble <sagar.a.kamble@xxxxxxxxx>
> Cc: Sujaritha Sundaresan <sujaritha.sundaresan@xxxxxxxxx>
> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@xxxxxxxxx>
> Cc: John Spotswood <john.a.spotswood@xxxxxxxxx>
> Cc: Oscar Mateo <oscar.mateo@xxxxxxxxx>
> Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
> Cc: Joonas Lahtinen <joonas.lahtinen@xxxxxxxxxxxxxxx>
> Reviewed-by: Sagar Arun Kamble <sagar.a.kamble@xxxxxxxxx> (v8)
> Signed-off-by: Jackie Li <yaodong.li@xxxxxxxxx>

<SNIP>

> --- 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)

This is intel_guc_wopcm file, so context_reserved_size() would be enough. But if
you feel like it is needed in the usage context, it's ok this way too.

> +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);
> +       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;
> +
> +       if (reserved >= WOPCM_DEFAULT_SIZE)
> +               return -E2BIG;
> +
> +       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;
> +

Unless we're expecting a u32 wrap-around, could not we consolidate these
checks some? At least just checking offset against WOPCM_DEFAULT_SIZE
feels repetitive when in the next moment, we check ALIGN(offset) +
reserved vs. same limit.

> +       top = WOPCM_DEFAULT_SIZE - offset;
> +       size = top - reserved;
> +
> +       /* GuC WOPCM size must be multiple of 4K pages */
> +       size &= PAGE_MASK;
> +
> +       /*
> +        * 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);
> +       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;
>  }

<SNIP>

>  /*
> - * 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   |
> + *   |     +==>+====================+<== 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.
> + */
> +

This diagram is a nice touch!

> +/* Default WOPCM size 1MB. */
> +#define WOPCM_DEFAULT_SIZE             (0x1 << 20)
> +/* The initial 16KB WOPCM (RSVD WOPCM) is reserved. */
> +#define WOPCM_RESERVED_SIZE            (16 << 10)

We might want to throw these to a more generic place, but they'll do
here for now as this is the only user.

> +static inline void intel_guc_wopcm_init_early(struct intel_guc_wopcm *guc_wopcm)
> +{
> +       guc_wopcm->top = WOPCM_DEFAULT_SIZE;
> +}

For header file brevity, move the implementation + comment to the .c file,
static inline header functions are an optimization for speed critical and often
used functions, which this definitely is not.

With the init_early function moved (and other changes at your
discretion) this is:

Reviewed-by: Joonas Lahtinen <joonas.lahtinen@xxxxxxxxxxxxxxx>

Regards, Joonas
_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux