1 // SPDX-License-Identifier: MIT 2 /* Copyright © 2025 Intel Corporation */ 3 4 #include "i915_drv.h" 5 #include "i915_gem_object_frontbuffer.h" 6 7 static int frontbuffer_active(struct i915_active *ref) 8 { 9 struct i915_frontbuffer *front = 10 container_of(ref, typeof(*front), write); 11 12 kref_get(&front->ref); 13 return 0; 14 } 15 16 static void frontbuffer_retire(struct i915_active *ref) 17 { 18 struct i915_frontbuffer *front = 19 container_of(ref, typeof(*front), write); 20 21 intel_frontbuffer_flush(&front->base, ORIGIN_CS); 22 i915_gem_object_frontbuffer_put(front); 23 } 24 25 struct i915_frontbuffer * 26 i915_gem_object_frontbuffer_get(struct drm_i915_gem_object *obj) 27 { 28 struct drm_i915_private *i915 = to_i915(obj->base.dev); 29 struct i915_frontbuffer *front, *cur; 30 31 front = i915_gem_object_frontbuffer_lookup(obj); 32 if (front) 33 return front; 34 35 front = kmalloc(sizeof(*front), GFP_KERNEL); 36 if (!front) 37 return NULL; 38 39 intel_frontbuffer_init(&front->base, &i915->drm); 40 41 kref_init(&front->ref); 42 i915_gem_object_get(obj); 43 front->obj = obj; 44 45 i915_active_init(&front->write, 46 frontbuffer_active, 47 frontbuffer_retire, 48 I915_ACTIVE_RETIRE_SLEEPS); 49 50 spin_lock(&i915->frontbuffer_lock); 51 if (rcu_access_pointer(obj->frontbuffer)) { 52 cur = rcu_dereference_protected(obj->frontbuffer, true); 53 kref_get(&cur->ref); 54 } else { 55 cur = front; 56 rcu_assign_pointer(obj->frontbuffer, front); 57 } 58 spin_unlock(&i915->frontbuffer_lock); 59 60 if (cur != front) { 61 i915_gem_object_put(obj); 62 intel_frontbuffer_fini(&front->base); 63 kfree(front); 64 } 65 66 return cur; 67 } 68 69 void i915_gem_object_frontbuffer_ref(struct i915_frontbuffer *front) 70 { 71 kref_get(&front->ref); 72 } 73 74 static void frontbuffer_release(struct kref *ref) 75 __releases(&i915->frontbuffer_lock) 76 { 77 struct i915_frontbuffer *front = 78 container_of(ref, typeof(*front), ref); 79 struct drm_i915_gem_object *obj = front->obj; 80 struct drm_i915_private *i915 = to_i915(obj->base.dev); 81 82 i915_ggtt_clear_scanout(obj); 83 84 RCU_INIT_POINTER(obj->frontbuffer, NULL); 85 86 spin_unlock(&i915->frontbuffer_lock); 87 88 i915_active_fini(&front->write); 89 90 i915_gem_object_put(obj); 91 92 intel_frontbuffer_fini(&front->base); 93 94 kfree_rcu(front, rcu); 95 } 96 97 void i915_gem_object_frontbuffer_put(struct i915_frontbuffer *front) 98 { 99 struct drm_i915_private *i915 = to_i915(front->obj->base.dev); 100 101 kref_put_lock(&front->ref, frontbuffer_release, 102 &i915->frontbuffer_lock); 103 } 104