[Intel-gfx] [PATCH 2/7] drm/i915/tgl: Make sure a semiplanar UV plane is tile row size aligned
Kahola, Mika
mika.kahola at intel.com
Thu Jan 2 14:12:31 UTC 2020
On Wed, 2020-01-01 at 01:37 +0200, Imre Deak wrote:
> Currently the GGTT offset of a UV plane in a semiplanar YUV FB is
> tile
> size (4kB) aligned. I noticed, that enforcing only this alignment
> leads
> oddly to random memory corruptions on TGL while scanning out Y-tiled
> FBs. This issue can be easily reproduced with a UV plane offset that
> is
> not aligned to the plane's tile row size.
>
> Some experiments showed the correct alignment to be tile row size
> indeed. This also makes sense, since the de-tiling fence created for
> the
> object - with its own stride and so "left" and "right" edge - applies
> to
> all the planes in the FB, so each tile row of all planes should be
> tile
> row aligned.
>
> In fact BSpec requires this alignment since SKL. On SKL we may
> enforce
> this due to the AUX plane x,y coords check, but on ICL and TGL we
> don't.
> For now enforce this only on TGL; I can follow up with any necessary
> change for ICL after more tests.
>
> BSpec requires a stricter alignment for linear UV planes too (kind of
> a
> tile row alignment), but it's unclear whether that's really needed
> (couldn't be explained with the de-tiling fence as above) and
> enforcing
> that could break existing user space; so avoid that too for now until
> more tests.
>
> v2:
> - Clarify the commit log wrt. the address space the alignment applies
> to.
> (Chris)
>
> Cc: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak at intel.com>
> Acked-by: Chris Wilson <chris at chris-wilson.co.uk>
Reviewed-by: Mika Kahola <mika.kahola at intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_display.c | 36
> ++++++++++++++++++--
> 1 file changed, 33 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> b/drivers/gpu/drm/i915/display/intel_display.c
> index 6e4152770c15..bbc9cf288067 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -1995,6 +1995,13 @@ intel_format_info_is_yuv_semiplanar(const
> struct drm_format_info *info,
> info->num_planes == (is_ccs_modifier(modifier) ? 4 : 2);
> }
>
> +static bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb,
> + int color_plane)
> +{
> + return intel_format_info_is_yuv_semiplanar(fb->format, fb-
> >modifier) &&
> + color_plane == 1;
> +}
> +
> static unsigned int
> intel_tile_width_bytes(const struct drm_framebuffer *fb, int
> color_plane)
> {
> @@ -2069,6 +2076,16 @@ static void intel_tile_dims(const struct
> drm_framebuffer *fb, int color_plane,
> *tile_height = intel_tile_height(fb, color_plane);
> }
>
> +static unsigned int intel_tile_row_size(const struct drm_framebuffer
> *fb,
> + int color_plane)
> +{
> + unsigned int tile_width, tile_height;
> +
> + intel_tile_dims(fb, color_plane, &tile_width, &tile_height);
> +
> + return fb->pitches[color_plane] * tile_height;
> +}
> +
> unsigned int
> intel_fb_align_height(const struct drm_framebuffer *fb,
> int color_plane, unsigned int height)
> @@ -2143,7 +2160,8 @@ static unsigned int intel_surf_alignment(const
> struct drm_framebuffer *fb,
> struct drm_i915_private *dev_priv = to_i915(fb->dev);
>
> /* AUX_DIST needs only 4K alignment */
> - if (is_aux_plane(fb, color_plane))
> + if ((INTEL_GEN(dev_priv) < 12 && is_aux_plane(fb, color_plane))
> ||
> + is_ccs_plane(fb, color_plane))
> return 4096;
>
> switch (fb->modifier) {
> @@ -2158,6 +2176,10 @@ static unsigned int intel_surf_alignment(const
> struct drm_framebuffer *fb,
> case I915_FORMAT_MOD_Y_TILED_CCS:
> case I915_FORMAT_MOD_Yf_TILED_CCS:
> case I915_FORMAT_MOD_Y_TILED:
> + if (INTEL_GEN(dev_priv) >= 12 &&
> + is_semiplanar_uv_plane(fb, color_plane))
> + return intel_tile_row_size(fb, color_plane);
> + /* Fall-through */
> case I915_FORMAT_MOD_Yf_TILED:
> return 1 * 1024 * 1024;
> default:
> @@ -2505,9 +2527,17 @@ static int intel_fb_offset_to_xy(int *x, int
> *y,
> {
> struct drm_i915_private *dev_priv = to_i915(fb->dev);
> unsigned int height;
> + u32 alignment;
> +
> + if (INTEL_GEN(dev_priv) >= 12 &&
> + is_semiplanar_uv_plane(fb, color_plane))
> + alignment = intel_tile_row_size(fb, color_plane);
> + else if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
> + alignment = intel_tile_size(dev_priv);
> + else
> + alignment = 0;
>
> - if (fb->modifier != DRM_FORMAT_MOD_LINEAR &&
> - fb->offsets[color_plane] % intel_tile_size(dev_priv)) {
> + if (alignment != 0 && fb->offsets[color_plane] % alignment) {
> DRM_DEBUG_KMS("Misaligned offset 0x%08x for color plane
> %d\n",
> fb->offsets[color_plane], color_plane);
> return -EINVAL;
More information about the Intel-gfx
mailing list