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 15void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj, 16 enum fb_op_origin origin); 17void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj, 18 enum fb_op_origin origin); 19 20static inline void 21i915_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 28static inline void 29i915_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 */ 45static inline struct intel_frontbuffer * 46i915_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 */ 84static inline struct intel_frontbuffer * 85i915_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(&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