1// SPDX-License-Identifier: MIT
2/* Copyright © 2025 Intel Corporation */
3
4#include "i915_drv.h"
5#include "i915_gem_object_frontbuffer.h"
6
7static int frontbuffer_active(struct i915_active *ref)
8{
9 struct i915_frontbuffer *front =
10 container_of(ref, typeof(*front), write);
11
12 kref_get(kref: &front->ref);
13 return 0;
14}
15
16static 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: &front->base, origin: ORIGIN_CS);
22 i915_gem_object_frontbuffer_put(front);
23}
24
25struct i915_frontbuffer *
26i915_gem_object_frontbuffer_get(struct drm_i915_gem_object *obj)
27{
28 struct drm_i915_private *i915 = to_i915(dev: 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: &front->base, drm: &i915->drm);
40
41 kref_init(kref: &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(lock: &i915->frontbuffer_lock);
51 if (rcu_access_pointer(obj->frontbuffer)) {
52 cur = rcu_dereference_protected(obj->frontbuffer, true);
53 kref_get(kref: &cur->ref);
54 } else {
55 cur = front;
56 rcu_assign_pointer(obj->frontbuffer, front);
57 }
58 spin_unlock(lock: &i915->frontbuffer_lock);
59
60 if (cur != front) {
61 i915_gem_object_put(obj);
62 intel_frontbuffer_fini(front: &front->base);
63 kfree(objp: front);
64 }
65
66 return cur;
67}
68
69void i915_gem_object_frontbuffer_ref(struct i915_frontbuffer *front)
70{
71 kref_get(kref: &front->ref);
72}
73
74static 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(dev: obj->base.dev);
81
82 i915_ggtt_clear_scanout(obj);
83
84 RCU_INIT_POINTER(obj->frontbuffer, NULL);
85
86 spin_unlock(lock: &i915->frontbuffer_lock);
87
88 i915_active_fini(ref: &front->write);
89
90 i915_gem_object_put(obj);
91
92 intel_frontbuffer_fini(front: &front->base);
93
94 kfree_rcu(front, rcu);
95}
96
97void i915_gem_object_frontbuffer_put(struct i915_frontbuffer *front)
98{
99 struct drm_i915_private *i915 = to_i915(dev: front->obj->base.dev);
100
101 kref_put_lock(kref: &front->ref, release: frontbuffer_release,
102 lock: &i915->frontbuffer_lock);
103}
104

source code of linux/drivers/gpu/drm/i915/gem/i915_gem_object_frontbuffer.c