1 /* SPDX-License-Identifier: GPL-2.0 OR MIT */ 2 3 #ifndef __DRM_EXEC_H__ 4 #define __DRM_EXEC_H__ 5 6 #include <linux/compiler.h> 7 #include <linux/ww_mutex.h> 8 9 #define DRM_EXEC_INTERRUPTIBLE_WAIT BIT(0) 10 #define DRM_EXEC_IGNORE_DUPLICATES BIT(1) 11 12 /* 13 * Dummy value used to initially enter the retry loop. 14 * internal use only. 15 */ 16 #define DRM_EXEC_DUMMY ((void *)~0) 17 18 struct drm_gem_object; 19 20 /** 21 * struct drm_exec - Execution context 22 */ 23 struct drm_exec { 24 /** 25 * @flags: Flags to control locking behavior 26 */ 27 u32 flags; 28 29 /** 30 * @ticket: WW ticket used for acquiring locks 31 */ 32 struct ww_acquire_ctx ticket; 33 34 /** 35 * @num_objects: number of objects locked 36 */ 37 unsigned int num_objects; 38 39 /** 40 * @max_objects: maximum objects in array 41 */ 42 unsigned int max_objects; 43 44 /** 45 * @objects: array of the locked objects 46 */ 47 struct drm_gem_object **objects; 48 49 /** 50 * @contended: contended GEM object we backed off for 51 */ 52 struct drm_gem_object *contended; 53 54 /** 55 * @prelocked: already locked GEM object due to contention 56 */ 57 struct drm_gem_object *prelocked; 58 }; 59 60 /** 61 * drm_exec_obj() - Return the object for a give drm_exec index 62 * @exec: Pointer to the drm_exec context 63 * @index: The index. 64 * 65 * Return: Pointer to the locked object corresponding to @index if 66 * index is within the number of locked objects. NULL otherwise. 67 */ 68 static inline struct drm_gem_object * 69 drm_exec_obj(struct drm_exec *exec, unsigned long index) 70 { 71 return index < exec->num_objects ? exec->objects[index] : NULL; 72 } 73 74 /* Helper for drm_exec_for_each_locked_object(). Internal use only. */ 75 #define __drm_exec_for_each_locked_object(exec, obj, __index) \ 76 for (unsigned long __index = 0; ((obj) = drm_exec_obj(exec, __index)); \ 77 ++__index) 78 /** 79 * drm_exec_for_each_locked_object - iterate over all the locked objects 80 * @exec: drm_exec object 81 * @obj: the current GEM object 82 * 83 * Iterate over all the explicitly locked GEM objects inside the drm_exec 84 * container, except for the contended and implicit prelocked one. 85 */ 86 #define drm_exec_for_each_locked_object(exec, obj) \ 87 __drm_exec_for_each_locked_object(exec, obj, __UNIQUE_ID(drm_exec)) 88 89 /* Helper for drm_exec_for_each_locked_object_reverse(). Internal use only. */ 90 #define __drm_exec_for_each_locked_object_reverse(exec, obj, __index) \ 91 for (unsigned long __index = (exec)->num_objects - 1; \ 92 ((obj) = drm_exec_obj(exec, __index)); --__index) 93 /** 94 * drm_exec_for_each_locked_object_reverse - iterate over all the locked 95 * objects in reverse locking order 96 * @exec: drm_exec object 97 * @obj: the current GEM object 98 * 99 * Iterate over all the explicitly locked GEM objects inside the drm_exec 100 * container in reverse locking order. Note that the internal index may wrap 101 * around, but that will be caught by drm_exec_obj(), returning a NULL object. 102 */ 103 #define drm_exec_for_each_locked_object_reverse(exec, obj) \ 104 __drm_exec_for_each_locked_object_reverse(exec, obj, \ 105 __UNIQUE_ID(drm_exec)) 106 107 /** 108 * drm_exec_until_all_locked - loop until all GEM objects are locked 109 * @exec: drm_exec object 110 * 111 * Core functionality of the drm_exec object. Loops until all GEM objects are 112 * locked and no more contention exists. At the beginning of the loop it is 113 * guaranteed that no GEM object is locked. 114 * 115 * A global label name drm_exec_retry is used, if you need to use more than one 116 * instance of this macro in the same function the label needs to be made local 117 * to the block with the __label__ keyword. 118 */ 119 #define drm_exec_until_all_locked(exec) \ 120 for (bool const __maybe_unused __drm_exec_loop = false; \ 121 drm_exec_cleanup(exec);) \ 122 if (false) { \ 123 drm_exec_retry: __maybe_unused; \ 124 continue; \ 125 } else 126 127 /** 128 * drm_exec_retry_on_contention - restart the loop to grap all locks 129 * @exec: drm_exec object 130 * 131 * Control flow helper to continue when a contention was detected and we need to 132 * clean up and re-start the loop to prepare all GEM objects. 133 * The __drm_exec_loop check exists to prevent usage outside of an 134 * drm_exec_until_all_locked() loop. 135 */ 136 #define drm_exec_retry_on_contention(exec) \ 137 do { \ 138 if (unlikely(drm_exec_is_contended(exec))) \ 139 goto drm_exec_retry; \ 140 } while (__drm_exec_loop) 141 142 /** 143 * drm_exec_is_contended - check for contention 144 * @exec: drm_exec object 145 * 146 * Returns true if the drm_exec object has run into some contention while 147 * locking a GEM object and needs to clean up. 148 */ 149 static inline bool drm_exec_is_contended(struct drm_exec *exec) 150 { 151 return !!exec->contended; 152 } 153 154 /** 155 * drm_exec_retry() - Unconditionally restart the loop to grab all locks. 156 * @exec: drm_exec object 157 * 158 * Unconditionally retry the loop to lock all objects. For consistency, 159 * the exec object needs to be newly initialized. 160 * The __drm_exec_loop check exists to prevent usage outside of an 161 * drm_exec_until_all_locked() loop. 162 */ 163 #define drm_exec_retry(_exec) \ 164 do { \ 165 WARN_ON((_exec)->contended != DRM_EXEC_DUMMY); \ 166 goto drm_exec_retry; \ 167 } while (__drm_exec_loop) 168 169 /** 170 * drm_exec_ticket - return the ww_acquire_ctx for this exec context 171 * @exec: drm_exec object 172 * 173 * Return: Pointer to the ww_acquire_ctx embedded in @exec. 174 */ 175 static inline struct ww_acquire_ctx *drm_exec_ticket(struct drm_exec *exec) 176 { 177 return &exec->ticket; 178 } 179 180 void drm_exec_init(struct drm_exec *exec, u32 flags, unsigned nr); 181 void drm_exec_fini(struct drm_exec *exec); 182 bool drm_exec_cleanup(struct drm_exec *exec); 183 int drm_exec_lock_obj(struct drm_exec *exec, struct drm_gem_object *obj); 184 void drm_exec_unlock_obj(struct drm_exec *exec, struct drm_gem_object *obj); 185 int drm_exec_prepare_obj(struct drm_exec *exec, struct drm_gem_object *obj, 186 unsigned int num_fences); 187 int drm_exec_prepare_array(struct drm_exec *exec, 188 struct drm_gem_object **objects, 189 unsigned int num_objects, 190 unsigned int num_fences); 191 192 #endif 193