1 | /* SPDX-License-Identifier: MIT */ |
2 | /* |
3 | * Copyright © 2023 Intel Corporation |
4 | */ |
5 | |
6 | #ifndef __I915_GEM_OBJECT_FRONTBUFFER_H__ |
7 | #define __I915_GEM_OBJECT_FRONTBUFFER_H__ |
8 | |
9 | #include <linux/kref.h> |
10 | #include <linux/rcupdate.h> |
11 | |
12 | #include "display/intel_frontbuffer.h" |
13 | #include "i915_gem_object_types.h" |
14 | |
15 | void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj, |
16 | enum fb_op_origin origin); |
17 | void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj, |
18 | enum fb_op_origin origin); |
19 | |
20 | static inline void |
21 | i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj, |
22 | enum fb_op_origin origin) |
23 | { |
24 | if (unlikely(rcu_access_pointer(obj->frontbuffer))) |
25 | __i915_gem_object_flush_frontbuffer(obj, origin); |
26 | } |
27 | |
28 | static inline void |
29 | i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj, |
30 | enum fb_op_origin origin) |
31 | { |
32 | if (unlikely(rcu_access_pointer(obj->frontbuffer))) |
33 | __i915_gem_object_invalidate_frontbuffer(obj, origin); |
34 | } |
35 | |
36 | /** |
37 | * i915_gem_object_get_frontbuffer - Get the object's frontbuffer |
38 | * @obj: The object whose frontbuffer to get. |
39 | * |
40 | * Get pointer to object's frontbuffer if such exists. Please note that RCU |
41 | * mechanism is used to handle e.g. ongoing removal of frontbuffer pointer. |
42 | * |
43 | * Return: pointer to object's frontbuffer is such exists or NULL |
44 | */ |
45 | static inline struct intel_frontbuffer * |
46 | i915_gem_object_get_frontbuffer(const struct drm_i915_gem_object *obj) |
47 | { |
48 | struct intel_frontbuffer *front; |
49 | |
50 | if (likely(!rcu_access_pointer(obj->frontbuffer))) |
51 | return NULL; |
52 | |
53 | rcu_read_lock(); |
54 | do { |
55 | front = rcu_dereference(obj->frontbuffer); |
56 | if (!front) |
57 | break; |
58 | |
59 | if (unlikely(!kref_get_unless_zero(&front->ref))) |
60 | continue; |
61 | |
62 | if (likely(front == rcu_access_pointer(obj->frontbuffer))) |
63 | break; |
64 | |
65 | intel_frontbuffer_put(front); |
66 | } while (1); |
67 | rcu_read_unlock(); |
68 | |
69 | return front; |
70 | } |
71 | |
72 | /** |
73 | * i915_gem_object_set_frontbuffer - Set the object's frontbuffer |
74 | * @obj: The object whose frontbuffer to set. |
75 | * @front: The frontbuffer to set |
76 | * |
77 | * Set object's frontbuffer pointer. If frontbuffer is already set for the |
78 | * object keep it and return it's pointer to the caller. Please note that RCU |
79 | * mechanism is used to handle e.g. ongoing removal of frontbuffer pointer. This |
80 | * function is protected by i915->display.fb_tracking.lock |
81 | * |
82 | * Return: pointer to frontbuffer which was set. |
83 | */ |
84 | static inline struct intel_frontbuffer * |
85 | i915_gem_object_set_frontbuffer(struct drm_i915_gem_object *obj, |
86 | struct intel_frontbuffer *front) |
87 | { |
88 | struct intel_frontbuffer *cur = front; |
89 | |
90 | if (!front) { |
91 | RCU_INIT_POINTER(obj->frontbuffer, NULL); |
92 | drm_gem_object_put(intel_bo_to_drm_bo(obj)); |
93 | } else if (rcu_access_pointer(obj->frontbuffer)) { |
94 | cur = rcu_dereference_protected(obj->frontbuffer, true); |
95 | kref_get(kref: &cur->ref); |
96 | } else { |
97 | drm_gem_object_get(intel_bo_to_drm_bo(obj)); |
98 | rcu_assign_pointer(obj->frontbuffer, front); |
99 | } |
100 | |
101 | return cur; |
102 | } |
103 | |
104 | #endif |
105 | |