]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/i915: Calculate the VT-d guard size in the display code
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Wed, 22 Jan 2025 15:17:53 +0000 (17:17 +0200)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 6 Feb 2025 13:35:44 +0000 (15:35 +0200)
Currently i915_gem_object_pin_to_display_plane() uses
i915_gem_object_get_tile_row_size() to calculate the tile row
size for the VT-d guard w/a. That's not really proper since
i915_gem_object_get_tile_row_size() only works for fenced BOs,
nor does it take rotation into account.

Remedy the situation by calculating the VT-d guard size in the
display code where we have more information readily available.
Although the default guard size (168 PTEs now) should cover
the more typical fb size use cases anyway, and only very large
Y/Yf-tiled framebuffers might have tile row size that exceeds it.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250122151755.6928-4-ville.syrjala@linux.intel.com
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
drivers/gpu/drm/i915/display/intel_fb.c
drivers/gpu/drm/i915/display/intel_fb.h
drivers/gpu/drm/i915/display/intel_fb_pin.c
drivers/gpu/drm/i915/display/intel_fb_pin.h
drivers/gpu/drm/i915/display/intel_fbdev.c
drivers/gpu/drm/i915/display/intel_overlay.c
drivers/gpu/drm/i915/gem/i915_gem_domain.c
drivers/gpu/drm/i915/gem/i915_gem_object.h
drivers/gpu/drm/xe/display/xe_fb_pin.c
drivers/gpu/drm/xe/display/xe_plane_initial.c

index 9f7f1b9f32750d1967b2a2e6c9fb6d5e2b968bb8..ea8c8a99c5c7e8415691c508c1ce8c29a95c9255 100644 (file)
@@ -1761,6 +1761,39 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *
        return 0;
 }
 
+unsigned int intel_fb_view_vtd_guard(const struct drm_framebuffer *fb,
+                                    const struct intel_fb_view *view,
+                                    unsigned int rotation)
+{
+       struct drm_i915_private *i915 = to_i915(fb->dev);
+       unsigned int vtd_guard;
+       int color_plane;
+
+       if (!intel_scanout_needs_vtd_wa(i915))
+               return 0;
+
+       vtd_guard = 168;
+
+       for (color_plane = 0; color_plane < fb->format->num_planes; color_plane++) {
+               unsigned int stride, tile;
+
+               if (intel_fb_is_ccs_aux_plane(fb, color_plane) ||
+                   is_gen12_ccs_cc_plane(fb, color_plane))
+                       continue;
+
+               stride = view->color_plane[color_plane].mapping_stride;
+
+               if (drm_rotation_90_or_270(rotation))
+                       tile = intel_tile_height(fb, color_plane);
+               else
+                       tile = intel_tile_width_bytes(fb, color_plane);
+
+               vtd_guard = max(vtd_guard, DIV_ROUND_UP(stride, tile));
+       }
+
+       return vtd_guard;
+}
+
 static void intel_plane_remap_gtt(struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *i915 =
index d78993e5eb629dac8a449f09f3b358747c6d3cb4..026e9f7f98f7d491844663ee3f22750c56536428 100644 (file)
@@ -83,6 +83,9 @@ bool intel_fb_supports_90_270_rotation(const struct intel_framebuffer *fb);
 int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *fb);
 void intel_fb_fill_view(const struct intel_framebuffer *fb, unsigned int rotation,
                        struct intel_fb_view *view);
+unsigned int intel_fb_view_vtd_guard(const struct drm_framebuffer *fb,
+                                    const struct intel_fb_view *view,
+                                    unsigned int rotation);
 int intel_plane_compute_gtt(struct intel_plane_state *plane_state);
 
 int intel_framebuffer_init(struct intel_framebuffer *ifb,
index 2b9ad46eaef7f69aca77d223d177026b564b6bd3..204e7e3e48cac684339891a31a9532879a929f6d 100644 (file)
@@ -107,6 +107,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb,
                     const struct i915_gtt_view *view,
                     unsigned int alignment,
                     unsigned int phys_alignment,
+                    unsigned int vtd_guard,
                     bool uses_fence,
                     unsigned long *out_flags)
 {
@@ -162,7 +163,7 @@ retry:
                goto err;
 
        vma = i915_gem_object_pin_to_display_plane(obj, &ww, alignment,
-                                                  view, pinctl);
+                                                  vtd_guard, view, pinctl);
        if (IS_ERR(vma)) {
                ret = PTR_ERR(vma);
                goto err_unpin;
@@ -244,6 +245,14 @@ intel_plane_fb_min_phys_alignment(const struct intel_plane_state *plane_state)
        return plane->min_alignment(plane, fb, 0);
 }
 
+static unsigned int
+intel_plane_fb_vtd_guard(const struct intel_plane_state *plane_state)
+{
+       return intel_fb_view_vtd_guard(plane_state->hw.fb,
+                                      &plane_state->view,
+                                      plane_state->hw.rotation);
+}
+
 int intel_plane_pin_fb(struct intel_plane_state *plane_state,
                       const struct intel_plane_state *old_plane_state)
 {
@@ -256,6 +265,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state,
                vma = intel_fb_pin_to_ggtt(&fb->base, &plane_state->view.gtt,
                                           intel_plane_fb_min_alignment(plane_state),
                                           intel_plane_fb_min_phys_alignment(plane_state),
+                                          intel_plane_fb_vtd_guard(plane_state),
                                           intel_plane_uses_fence(plane_state),
                                           &plane_state->flags);
                if (IS_ERR(vma))
index 0fc6d90446381123043ef14164f2d45df4b8d9ce..01770dbba2e08faeb58a8bfd2ea1f3aa9d46299f 100644 (file)
@@ -18,6 +18,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb,
                     const struct i915_gtt_view *view,
                     unsigned int alignment,
                     unsigned int phys_alignment,
+                    unsigned int vtd_guard,
                     bool uses_fence,
                     unsigned long *out_flags);
 
index 6c08081333976a588ed7c09ae5e44987e90207c0..833cded53d37037d0e42174698e19eb79838626b 100644 (file)
@@ -228,6 +228,8 @@ static int intelfb_create(struct drm_fb_helper *helper,
         */
        vma = intel_fb_pin_to_ggtt(&fb->base, &view,
                                   fb->min_alignment, 0,
+                                  intel_fb_view_vtd_guard(&fb->base, &fb->normal_view,
+                                                          DRM_MODE_ROTATE_0),
                                   false, &flags);
        if (IS_ERR(vma)) {
                ret = PTR_ERR(vma);
index bbb0db33740e9018e8c3cab5ced0b50ee63e6550..4d00db86131b61309fc5f98f8b0dd0570a5f71bf 100644 (file)
@@ -778,7 +778,7 @@ static struct i915_vma *intel_overlay_pin_fb(struct drm_i915_gem_object *new_bo)
 retry:
        ret = i915_gem_object_lock(new_bo, &ww);
        if (!ret) {
-               vma = i915_gem_object_pin_to_display_plane(new_bo, &ww, 0,
+               vma = i915_gem_object_pin_to_display_plane(new_bo, &ww, 0, 0,
                                                           NULL, PIN_MAPPABLE);
                ret = PTR_ERR_OR_ZERO(vma);
        }
index ee55caca67a11b7e892ad1b465eff58e75a77b24..75a143d996e0ec13b5e5abd2e1068609f56a121b 100644 (file)
@@ -18,8 +18,6 @@
 #include "i915_gem_object_frontbuffer.h"
 #include "i915_vma.h"
 
-#define VTD_GUARD (168u * I915_GTT_PAGE_SIZE) /* 168 or tile-row PTE padding */
-
 static bool gpu_write_needs_clflush(struct drm_i915_gem_object *obj)
 {
        struct drm_i915_private *i915 = to_i915(obj->base.dev);
@@ -424,7 +422,7 @@ out:
 struct i915_vma *
 i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
                                     struct i915_gem_ww_ctx *ww,
-                                    u32 alignment,
+                                    u32 alignment, unsigned int guard,
                                     const struct i915_gtt_view *view,
                                     unsigned int flags)
 {
@@ -453,15 +451,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
                return ERR_PTR(ret);
 
        /* VT-d may overfetch before/after the vma, so pad with scratch */
-       if (intel_scanout_needs_vtd_wa(i915)) {
-               unsigned int guard = VTD_GUARD;
-
-               if (i915_gem_object_is_tiled(obj))
-                       guard = max(guard,
-                                   i915_gem_object_get_tile_row_size(obj));
-
-               flags |= PIN_OFFSET_GUARD | guard;
-       }
+       if (guard)
+               flags |= PIN_OFFSET_GUARD | (guard * I915_GTT_PAGE_SIZE);
 
        /*
         * As the user may map the buffer once pinned in the display plane
index bb713e096db287938eb1aa73ee40a16fcd85e699..a5f34542135ce2d14005d23c366fe6ff290d9454 100644 (file)
@@ -776,7 +776,7 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write);
 struct i915_vma * __must_check
 i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
                                     struct i915_gem_ww_ctx *ww,
-                                    u32 alignment,
+                                    u32 alignment, unsigned int guard,
                                     const struct i915_gtt_view *view,
                                     unsigned int flags);
 
index 25ce032bb293fb8128bdbe564d7351ef775e7c75..11a6b996d739be5bf63ad981d8e1be6c16136bf3 100644 (file)
@@ -369,6 +369,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb,
                     const struct i915_gtt_view *view,
                     unsigned int alignment,
                     unsigned int phys_alignment,
+                    unsigned int vtd_guard,
                     bool uses_fence,
                     unsigned long *out_flags)
 {
index 2a2f250fa495d03dcfd442a821c8fc10413a2511..25c80dd6d386337437bf1c46dc5e6622852c42a6 100644 (file)
@@ -215,7 +215,7 @@ intel_find_initial_plane_obj(struct intel_crtc *crtc,
                           plane_state->uapi.rotation, &plane_state->view);
 
        vma = intel_fb_pin_to_ggtt(fb, &plane_state->view.gtt,
-                                  0, 0, false, &plane_state->flags);
+                                  0, 0, 0, false, &plane_state->flags);
        if (IS_ERR(vma))
                goto nofb;