1 // SPDX-License-Identifier: MIT
2 /* Copyright © 2025 Intel Corporation */
3
4 #include "i915_drv.h"
5 #include "i915_gem_object_frontbuffer.h"
6
frontbuffer_active(struct i915_active * ref)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
frontbuffer_retire(struct i915_active * ref)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 *
i915_gem_object_frontbuffer_get(struct drm_i915_gem_object * obj)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_obj(*front);
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
i915_gem_object_frontbuffer_ref(struct i915_frontbuffer * front)69 void i915_gem_object_frontbuffer_ref(struct i915_frontbuffer *front)
70 {
71 kref_get(&front->ref);
72 }
73
frontbuffer_release(struct kref * ref)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
i915_gem_object_frontbuffer_put(struct i915_frontbuffer * front)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