Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>
(cherry picked from commit eb4d490729a5fd8dc5a76d334f8d01fec7c14bbe)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

authored by

Ville Syrjälä and committed by
Rodrigo Vivi
760039c9 1696b0cf

+9 -3
+9 -1
drivers/gpu/drm/i915/display/intel_frontbuffer.c
··· 270 270 spin_unlock(&display->fb_tracking.lock); 271 271 272 272 i915_active_fini(&front->write); 273 + 274 + drm_gem_object_put(obj); 273 275 kfree_rcu(front, rcu); 274 276 } 275 277 ··· 289 287 if (!front) 290 288 return NULL; 291 289 290 + drm_gem_object_get(obj); 291 + 292 292 front->obj = obj; 293 293 kref_init(&front->ref); 294 294 atomic_set(&front->bits, 0); ··· 303 299 spin_lock(&display->fb_tracking.lock); 304 300 cur = intel_bo_set_frontbuffer(obj, front); 305 301 spin_unlock(&display->fb_tracking.lock); 306 - if (cur != front) 302 + 303 + if (cur != front) { 304 + drm_gem_object_put(obj); 307 305 kfree(front); 306 + } 307 + 308 308 return cur; 309 309 } 310 310
-2
drivers/gpu/drm/i915/gem/i915_gem_object_frontbuffer.h
··· 89 89 90 90 if (!front) { 91 91 RCU_INIT_POINTER(obj->frontbuffer, NULL); 92 - drm_gem_object_put(intel_bo_to_drm_bo(obj)); 93 92 } else if (rcu_access_pointer(obj->frontbuffer)) { 94 93 cur = rcu_dereference_protected(obj->frontbuffer, true); 95 94 kref_get(&cur->ref); 96 95 } else { 97 - drm_gem_object_get(intel_bo_to_drm_bo(obj)); 98 96 rcu_assign_pointer(obj->frontbuffer, front); 99 97 } 100 98