Re: [PATCH v2 15/15] drm/i915: Try to relocate the BIOS fb to the start of ggtt

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

 



On Wed, Jan 10, 2024 at 11:11:10AM +0100, Andrzej Hajda wrote:
> On 15.12.2023 11:59, Ville Syrjala wrote:
> > From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>
> > 
> > On MTL the GOP (for whatever reason) likes to bind its framebuffer
> > high up in the ggtt address space. This can conflict with whatever
> > ggtt_reserve_guc_top() is trying to do, and the result is that
> > ggtt_reserve_guc_top() fails and then we proceed to explode when
> > trying to tear down the driver. Thus far I haven't analyzed what
> > causes the actual fireworks, but it's not super important as even
> > if it didn't explode we'd still fail the driver load and the user
> > would be left with an unusable GPU.
> > 
> > To remedy this (without having to figure out exactly what
> > ggtt_reserve_guc_top() is trying to achieve) we can attempt to
> > relocate the BIOS framebuffer to a lower ggtt address. We can do
> > this at this early point in driver init because nothing else is
> > supposed to be clobbering the ggtt yet. So we simply change where
> > in the ggtt we pin the vma, the original PTEs will be left as is,
> > and the new PTEs will get written with the same dma addresses.
> > The plane will keep on scanning out from the original PTEs until
> > we are done with the whole process, and at that point we rewrite
> > the plane's surface address register to point at the new ggtt
> > address.
> > 
> > Since we don't need a specific ggtt address for the plane
> > (apart from needing it to land in the mappable region for
> > normal stolen objects) we'll just try to pin it without a fixed
> > offset first. It should end up at the lowest available address
> > (which really should be 0 at this point in the driver init).
> > If that fails we'll fall back to just pinning it exactly to the
> > origianal address.
> > 
> > To make sure we don't accidentlally pin it partially over the
> > original ggtt range (as that would corrupt the original PTEs)
> > we reserve the original range temporarily during this process.
> > 
> > Cc: Paz Zcharya <pazz@xxxxxxxxxxxx>
> > Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>
> > ---
> >   drivers/gpu/drm/i915/display/i9xx_plane.c     | 30 ++++++++++
> >   drivers/gpu/drm/i915/display/i9xx_plane.h     |  7 +++
> >   drivers/gpu/drm/i915/display/intel_display.c  |  5 ++
> >   .../gpu/drm/i915/display/intel_display_core.h |  2 +
> >   .../drm/i915/display/intel_plane_initial.c    | 57 ++++++++++++++++++-
> >   .../drm/i915/display/skl_universal_plane.c    | 28 +++++++++
> >   .../drm/i915/display/skl_universal_plane.h    |  2 +
> >   7 files changed, 128 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c
> > index 91f2bc405cba..0279c8aabdd1 100644
> > --- a/drivers/gpu/drm/i915/display/i9xx_plane.c
> > +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c
> > @@ -1060,3 +1060,33 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
> >   
> >   	plane_config->fb = intel_fb;
> >   }
> > +
> > +bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc,
> > +				     const struct intel_initial_plane_config *plane_config)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> > +	struct intel_plane *plane = to_intel_plane(crtc->base.primary);
> > +	const struct intel_plane_state *plane_state =
> > +		to_intel_plane_state(plane->base.state);
> > +	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> > +	u32 base;
> > +
> > +	if (!plane_state->uapi.visible)
> > +		return false;
> > +
> > +	base = intel_plane_ggtt_offset(plane_state);
> > +
> > +	/*
> > +	 * We may have moved the surface to a different
> > +	 * part of ggtt, make the plane aware of that.
> > +	 */
> > +	if (plane_config->base == base)
> > +		return false;
> > +
> > +	if (DISPLAY_VER(dev_priv) >= 4)
> > +		intel_de_write(dev_priv, DSPSURF(i9xx_plane), base);
> > +	else
> > +		intel_de_write(dev_priv, DSPADDR(i9xx_plane), base);
> 
> It seems skl_fixup_initial_plane_config is the same, except 
> intel_de_write part. Couldn't we merge both functions into one and just 
> add another elseif branch here? Maybe abstracting out somehow surface 
> registers writes? Just loose ideas.
> However I wouldn't be surprised if there is good reason to keep it as is.

It's just that we generally want to keep the skl+ vs. pre-skl
low level plane code separate. There are enough differences between
them, so separate code is probably less messy than trying to share
it. And I don't think the common parts between this and its counterpart
are significant enough to really go against that.

> 
> Reviewed-by: Andrzej Hajda <andrzej.hajda@xxxxxxxxx>
> 
> Regards
> Andrzej
> 
> > +
> > +	return true;
> > +}
> > diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.h b/drivers/gpu/drm/i915/display/i9xx_plane.h
> > index b3d724a144cb..0ca12d1e6839 100644
> > --- a/drivers/gpu/drm/i915/display/i9xx_plane.h
> > +++ b/drivers/gpu/drm/i915/display/i9xx_plane.h
> > @@ -26,6 +26,8 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe);
> >   
> >   void i9xx_get_initial_plane_config(struct intel_crtc *crtc,
> >   				   struct intel_initial_plane_config *plane_config);
> > +bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc,
> > +				     const struct intel_initial_plane_config *plane_config);
> >   #else
> >   static inline unsigned int i965_plane_max_stride(struct intel_plane *plane,
> >   						 u32 pixel_format, u64 modifier,
> > @@ -46,6 +48,11 @@ static inline void i9xx_get_initial_plane_config(struct intel_crtc *crtc,
> >   						 struct intel_initial_plane_config *plane_config)
> >   {
> >   }
> > +static inline bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc,
> > +						   const struct intel_initial_plane_config *plane_config)
> > +{
> > +	return false;
> > +}
> >   #endif
> >   
> >   #endif
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > index d955957b7d18..92b4a894c9b9 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -7820,6 +7820,7 @@ static const struct intel_display_funcs skl_display_funcs = {
> >   	.crtc_disable = hsw_crtc_disable,
> >   	.commit_modeset_enables = skl_commit_modeset_enables,
> >   	.get_initial_plane_config = skl_get_initial_plane_config,
> > +	.fixup_initial_plane_config = skl_fixup_initial_plane_config,
> >   };
> >   
> >   static const struct intel_display_funcs ddi_display_funcs = {
> > @@ -7828,6 +7829,7 @@ static const struct intel_display_funcs ddi_display_funcs = {
> >   	.crtc_disable = hsw_crtc_disable,
> >   	.commit_modeset_enables = intel_commit_modeset_enables,
> >   	.get_initial_plane_config = i9xx_get_initial_plane_config,
> > +	.fixup_initial_plane_config = i9xx_fixup_initial_plane_config,
> >   };
> >   
> >   static const struct intel_display_funcs pch_split_display_funcs = {
> > @@ -7836,6 +7838,7 @@ static const struct intel_display_funcs pch_split_display_funcs = {
> >   	.crtc_disable = ilk_crtc_disable,
> >   	.commit_modeset_enables = intel_commit_modeset_enables,
> >   	.get_initial_plane_config = i9xx_get_initial_plane_config,
> > +	.fixup_initial_plane_config = i9xx_fixup_initial_plane_config,
> >   };
> >   
> >   static const struct intel_display_funcs vlv_display_funcs = {
> > @@ -7844,6 +7847,7 @@ static const struct intel_display_funcs vlv_display_funcs = {
> >   	.crtc_disable = i9xx_crtc_disable,
> >   	.commit_modeset_enables = intel_commit_modeset_enables,
> >   	.get_initial_plane_config = i9xx_get_initial_plane_config,
> > +	.fixup_initial_plane_config = i9xx_fixup_initial_plane_config,
> >   };
> >   
> >   static const struct intel_display_funcs i9xx_display_funcs = {
> > @@ -7852,6 +7856,7 @@ static const struct intel_display_funcs i9xx_display_funcs = {
> >   	.crtc_disable = i9xx_crtc_disable,
> >   	.commit_modeset_enables = intel_commit_modeset_enables,
> >   	.get_initial_plane_config = i9xx_get_initial_plane_config,
> > +	.fixup_initial_plane_config = i9xx_fixup_initial_plane_config,
> >   };
> >   
> >   /**
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
> > index 7e82b87e9cde..3f17328ff690 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_core.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
> > @@ -64,6 +64,8 @@ struct intel_display_funcs {
> >   				struct intel_crtc_state *);
> >   	void (*get_initial_plane_config)(struct intel_crtc *,
> >   					 struct intel_initial_plane_config *);
> > +	bool (*fixup_initial_plane_config)(struct intel_crtc *crtc,
> > +					   const struct intel_initial_plane_config *plane_config);
> >   	void (*crtc_enable)(struct intel_atomic_state *state,
> >   			    struct intel_crtc *crtc);
> >   	void (*crtc_disable)(struct intel_atomic_state *state,
> > diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c
> > index 82ab98985a09..72f509f8bc63 100644
> > --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c
> > +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c
> > @@ -3,9 +3,11 @@
> >    * Copyright © 2021 Intel Corporation
> >    */
> >   
> > +#include "gem/i915_gem_lmem.h"
> >   #include "gem/i915_gem_region.h"
> >   #include "i915_drv.h"
> >   #include "intel_atomic_plane.h"
> > +#include "intel_crtc.h"
> >   #include "intel_display.h"
> >   #include "intel_display_types.h"
> >   #include "intel_fb.h"
> > @@ -138,6 +140,7 @@ initial_plane_vma(struct drm_i915_private *i915,
> >   {
> >   	struct intel_memory_region *mem;
> >   	struct drm_i915_gem_object *obj;
> > +	struct drm_mm_node orig_mm = {};
> >   	struct i915_vma *vma;
> >   	resource_size_t phys_base;
> >   	u32 base, size;
> > @@ -195,23 +198,68 @@ initial_plane_vma(struct drm_i915_private *i915,
> >   		goto err_obj;
> >   	}
> >   
> > +	/*
> > +	 * MTL GOP likes to place the framebuffer high up in ggtt,
> > +	 * which can cause problems for ggtt_reserve_guc_top().
> > +	 * Try to pin it to a low ggtt address instead to avoid that.
> > +	 */
> > +	base = 0;
> > +
> > +	if (base != plane_config->base) {
> > +		struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
> > +		int ret;
> > +
> > +		/*
> > +		 * Make sure the original and new locations
> > +		 * can't overlap. That would corrupt the original
> > +		 * PTEs which are still being used for scanout.
> > +		 */
> > +		ret = i915_gem_gtt_reserve(&ggtt->vm, NULL, &orig_mm,
> > +					   size, plane_config->base,
> > +					   I915_COLOR_UNEVICTABLE, PIN_NOEVICT);
> > +		if (ret)
> > +			goto err_obj;
> > +	}
> > +
> >   	vma = i915_vma_instance(obj, &to_gt(i915)->ggtt->vm, NULL);
> >   	if (IS_ERR(vma))
> >   		goto err_obj;
> >   
> > -	pinctl = PIN_GLOBAL | PIN_OFFSET_FIXED | base;
> > -	if (HAS_GMCH(i915))
> > +retry:
> > +	pinctl = PIN_GLOBAL;
> > +	if (base == plane_config->base)
> > +		pinctl |= PIN_OFFSET_FIXED | base;
> > +	if (!i915_gem_object_is_lmem(obj))
> >   		pinctl |= PIN_MAPPABLE;
> > -	if (i915_vma_pin(vma, 0, 0, pinctl))
> > +	if (i915_vma_pin(vma, 0, 0, pinctl)) {
> > +		if (drm_mm_node_allocated(&orig_mm)) {
> > +			drm_mm_remove_node(&orig_mm);
> > +			/*
> > +			 * Try again, but this time pin
> > +			 * it to its original location.
> > +			 */
> > +			base = plane_config->base;
> > +			goto retry;
> > +		}
> >   		goto err_obj;
> > +	}
> >   
> >   	if (i915_gem_object_is_tiled(obj) &&
> >   	    !i915_vma_is_map_and_fenceable(vma))
> >   		goto err_obj;
> >   
> > +	if (drm_mm_node_allocated(&orig_mm))
> > +		drm_mm_remove_node(&orig_mm);
> > +
> > +	drm_dbg_kms(&i915->drm,
> > +		    "Initial plane fb bound to 0x%x in the ggtt (original 0x%x)\n",
> > +		    i915_ggtt_offset(vma), plane_config->base);
> > +
> >   	return vma;
> >   
> >   err_obj:
> > +	if (drm_mm_node_allocated(&orig_mm))
> > +		drm_mm_remove_node(&orig_mm);
> >   	i915_gem_object_put(obj);
> >   	return NULL;
> >   }
> > @@ -386,6 +434,9 @@ void intel_initial_plane_config(struct drm_i915_private *i915)
> >   		 */
> >   		intel_find_initial_plane_obj(crtc, plane_configs);
> >   
> > +		if (i915->display.funcs.display->fixup_initial_plane_config(crtc, plane_config))
> > +			intel_crtc_wait_for_next_vblank(crtc);
> > +
> >   		plane_config_fini(plane_config);
> >   	}
> >   }
> > diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> > index 511dc1544854..392d93e97bf8 100644
> > --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
> > +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> > @@ -2624,3 +2624,31 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
> >   error:
> >   	kfree(intel_fb);
> >   }
> > +
> > +bool skl_fixup_initial_plane_config(struct intel_crtc *crtc,
> > +				    const struct intel_initial_plane_config *plane_config)
> > +{
> > +	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
> > +	struct intel_plane *plane = to_intel_plane(crtc->base.primary);
> > +	const struct intel_plane_state *plane_state =
> > +		to_intel_plane_state(plane->base.state);
> > +	enum plane_id plane_id = plane->id;
> > +	enum pipe pipe = crtc->pipe;
> > +	u32 base;
> > +
> > +	if (!plane_state->uapi.visible)
> > +		return false;
> > +
> > +	base = intel_plane_ggtt_offset(plane_state);
> > +
> > +	/*
> > +	 * We may have moved the surface to a different
> > +	 * part of ggtt, make the plane aware of that.
> > +	 */
> > +	if (plane_config->base == base)
> > +		return false;
> > +
> > +	intel_de_write(i915, PLANE_SURF(pipe, plane_id), base);
> > +
> > +	return true;
> > +}
> > diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.h b/drivers/gpu/drm/i915/display/skl_universal_plane.h
> > index be64c201f9b3..e92e00c01b29 100644
> > --- a/drivers/gpu/drm/i915/display/skl_universal_plane.h
> > +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.h
> > @@ -22,6 +22,8 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
> >   
> >   void skl_get_initial_plane_config(struct intel_crtc *crtc,
> >   				  struct intel_initial_plane_config *plane_config);
> > +bool skl_fixup_initial_plane_config(struct intel_crtc *crtc,
> > +				    const struct intel_initial_plane_config *plane_config);
> >   
> >   int skl_format_to_fourcc(int format, bool rgb_order, bool alpha);
> >   

-- 
Ville Syrjälä
Intel



[Index of Archives]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux