| 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 |  | 
|---|