drm/i915: Pre-populate the cursor physical dma address
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Mon, 25 Mar 2024 17:57:38 +0000 (19:57 +0200)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Thu, 28 Mar 2024 16:16:16 +0000 (12:16 -0400)
Calling i915_gem_object_get_dma_address() from the vblank
evade critical section triggers might_sleep().

While we know that we've already pinned the framebuffer
and thus i915_gem_object_get_dma_address() will in fact
not sleep in this case, it seems reasonable to keep the
unconditional might_sleep() for maximum coverage.

So let's instead pre-populate the dma address during
fb pinning, which all happens before we enter the
vblank evade critical section.

We can use u32 for the dma address as this class of
hardware doesn't support >32bit addresses.

Cc: stable@vger.kernel.org
Fixes: 0225a90981c8 ("drm/i915: Make cursor plane registers unlocked")
Reported-by: Borislav Petkov <bp@alien8.de>
Closes: https://lore.kernel.org/intel-gfx/20240227100342.GAZd2zfmYcPS_SndtO@fat_crate.local/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240325175738.3440-1-ville.syrjala@linux.intel.com
Tested-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
(cherry picked from commit c1289a5c3594cf04caa94ebf0edeb50c62009f1f)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/i915/display/intel_cursor.c
drivers/gpu/drm/i915/display/intel_display_types.h
drivers/gpu/drm/i915/display/intel_fb_pin.c

index f8b33999d43fccdba84fd2f26f650356423d2bc3..0d3da55e1c24d51aa190f4b76aa7b20d5260038d 100644 (file)
@@ -36,12 +36,10 @@ static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv =
                to_i915(plane_state->uapi.plane->dev);
-       const struct drm_framebuffer *fb = plane_state->hw.fb;
-       struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        u32 base;
 
        if (DISPLAY_INFO(dev_priv)->cursor_needs_physical)
-               base = i915_gem_object_get_dma_address(obj, 0);
+               base = plane_state->phys_dma_addr;
        else
                base = intel_plane_ggtt_offset(plane_state);
 
index e67cd5b02e84ff859588fd152f147c35d4296e42..9104f18753b484fde2b439f85494fc77a3d27c87 100644 (file)
@@ -727,6 +727,7 @@ struct intel_plane_state {
 #define PLANE_HAS_FENCE BIT(0)
 
        struct intel_fb_view view;
+       u32 phys_dma_addr; /* for cursor_needs_physical */
 
        /* Plane pxp decryption state */
        bool decrypt;
index 7b42aef37d2f72275603e9f80950ae1edd55d203..b6df9baf481b6958ee42f35457b7b37c294ddb65 100644 (file)
@@ -255,6 +255,16 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state)
                        return PTR_ERR(vma);
 
                plane_state->ggtt_vma = vma;
+
+               /*
+                * Pre-populate the dma address before we enter the vblank
+                * evade critical section as i915_gem_object_get_dma_address()
+                * will trigger might_sleep() even if it won't actually sleep,
+                * which is the case when the fb has already been pinned.
+                */
+               if (phys_cursor)
+                       plane_state->phys_dma_addr =
+                               i915_gem_object_get_dma_address(intel_fb_obj(fb), 0);
        } else {
                struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);