diff options
| author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2024-02-03 00:43:39 +0200 |
|---|---|---|
| committer | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2024-02-07 02:01:49 +0200 |
| commit | a8153627520a2d468680bb7686fd404c222b13ca (patch) | |
| tree | 50104642cce50dbba8145cdfe9fb9fa6d61bb6f4 /drivers/gpu/drm/i915/display/intel_plane_initial.c | |
| parent | ea5e150ac2cf88f586299c06244d5a4d473c041e (diff) | |
drm/i915: Try to relocate the BIOS fb to the start of ggtt
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.
v2: Try to pin explicitly to ggtt offset 0 as otherwise DG2 puts it
even higher (atm we have no PIN_LOW flag to force it low)
v3: "fix" xe
Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
Tested-by: Paz Zcharya <pazz@chromium.org>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240202224340.30647-16-ville.syrjala@linux.intel.com
Acked-by: Lucas De Marchi <lucas.demarchi@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_plane_initial.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_plane_initial.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index 8203c6dd6f73..b43b8cf4680c 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,66 @@ 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; +retry: pinctl = PIN_GLOBAL | PIN_OFFSET_FIXED | base; - if (HAS_GMCH(i915)) + 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 +432,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); } } |