summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display/intel_frontbuffer.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2025-10-03 17:57:30 +0300
committerVille Syrjälä <ville.syrjala@linux.intel.com>2025-10-09 21:01:48 +0300
commiteb4d490729a5fd8dc5a76d334f8d01fec7c14bbe (patch)
tree948188851423a87f04c6a0dc9137fe691580d2fb /drivers/gpu/drm/i915/display/intel_frontbuffer.c
parent76e46dbf80918ef0dc8e489f88959bab48b6b9ce (diff)
drm/i915/frontbuffer: Move bo refcounting intel_frontbuffer_{get,release}()
Currently xe's intel_frontbuffer implementation forgets to hold a reference on the bo. This makes the entire thing extremely fragile as the cleanup order now depends on bo references held by other things (namely intel_fb_bo_framebuffer_fini()). Move the bo refcounting to intel_frontbuffer_{get,release}() so that both i915 and xe do this the same way. I first tried to fix this by having xe do the refcounting from its intel_bo_set_frontbuffer() implementation (which is what i915 does currently), but turns out xe's drm_gem_object_free() can sleep and thus drm_gem_object_put() isn't safe to call while we hold fb_tracking.lock. Fixes: 10690b8a49bc ("drm/i915/display: Add intel_fb_bo_framebuffer_fini") Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20251003145734.7634-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_frontbuffer.c')
-rw-r--r--drivers/gpu/drm/i915/display/intel_frontbuffer.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
index 43be5377ddc1..73ed28ac9573 100644
--- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c
+++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
@@ -270,6 +270,8 @@ static void frontbuffer_release(struct kref *ref)
spin_unlock(&display->fb_tracking.lock);
i915_active_fini(&front->write);
+
+ drm_gem_object_put(obj);
kfree_rcu(front, rcu);
}
@@ -287,6 +289,8 @@ intel_frontbuffer_get(struct drm_gem_object *obj)
if (!front)
return NULL;
+ drm_gem_object_get(obj);
+
front->obj = obj;
kref_init(&front->ref);
atomic_set(&front->bits, 0);
@@ -299,8 +303,12 @@ intel_frontbuffer_get(struct drm_gem_object *obj)
spin_lock(&display->fb_tracking.lock);
cur = intel_bo_set_frontbuffer(obj, front);
spin_unlock(&display->fb_tracking.lock);
- if (cur != front)
+
+ if (cur != front) {
+ drm_gem_object_put(obj);
kfree(front);
+ }
+
return cur;
}