Line data Source code
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 : struct drm_gem_object; 13 : 14 : /** 15 : * struct drm_exec - Execution context 16 : */ 17 : struct drm_exec { 18 : /** 19 : * @flags: Flags to control locking behavior 20 : */ 21 : uint32_t flags; 22 : 23 : /** 24 : * @ticket: WW ticket used for acquiring locks 25 : */ 26 : struct ww_acquire_ctx ticket; 27 : 28 : /** 29 : * @num_objects: number of objects locked 30 : */ 31 : unsigned int num_objects; 32 : 33 : /** 34 : * @max_objects: maximum objects in array 35 : */ 36 : unsigned int max_objects; 37 : 38 : /** 39 : * @objects: array of the locked objects 40 : */ 41 : struct drm_gem_object **objects; 42 : 43 : /** 44 : * @contended: contended GEM object we backed off for 45 : */ 46 : struct drm_gem_object *contended; 47 : 48 : /** 49 : * @prelocked: already locked GEM object due to contention 50 : */ 51 : struct drm_gem_object *prelocked; 52 : }; 53 : 54 : /** 55 : * drm_exec_for_each_locked_object - iterate over all the locked objects 56 : * @exec: drm_exec object 57 : * @index: unsigned long index for the iteration 58 : * @obj: the current GEM object 59 : * 60 : * Iterate over all the locked GEM objects inside the drm_exec object. 61 : */ 62 : #define drm_exec_for_each_locked_object(exec, index, obj) \ 63 : for (index = 0, obj = (exec)->objects[0]; \ 64 : index < (exec)->num_objects; \ 65 : ++index, obj = (exec)->objects[index]) 66 : 67 : /** 68 : * drm_exec_until_all_locked - loop until all GEM objects are locked 69 : * @exec: drm_exec object 70 : * 71 : * Core functionality of the drm_exec object. Loops until all GEM objects are 72 : * locked and no more contention exists. At the beginning of the loop it is 73 : * guaranteed that no GEM object is locked. 74 : * 75 : * Since labels can't be defined local to the loops body we use a jump pointer 76 : * to make sure that the retry is only used from within the loops body. 77 : */ 78 : #define drm_exec_until_all_locked(exec) \ 79 : __PASTE(__drm_exec_, __LINE__): \ 80 : for (void *__drm_exec_retry_ptr; ({ \ 81 : __drm_exec_retry_ptr = &&__PASTE(__drm_exec_, __LINE__);\ 82 : (void)__drm_exec_retry_ptr; \ 83 : drm_exec_cleanup(exec); \ 84 : });) 85 : 86 : /** 87 : * drm_exec_retry_on_contention - restart the loop to grap all locks 88 : * @exec: drm_exec object 89 : * 90 : * Control flow helper to continue when a contention was detected and we need to 91 : * clean up and re-start the loop to prepare all GEM objects. 92 : */ 93 : #define drm_exec_retry_on_contention(exec) \ 94 : do { \ 95 : if (unlikely(drm_exec_is_contended(exec))) \ 96 : goto *__drm_exec_retry_ptr; \ 97 : } while (0) 98 : 99 : /** 100 : * drm_exec_is_contended - check for contention 101 : * @exec: drm_exec object 102 : * 103 : * Returns true if the drm_exec object has run into some contention while 104 : * locking a GEM object and needs to clean up. 105 : */ 106 : static inline bool drm_exec_is_contended(struct drm_exec *exec) 107 : { 108 0 : return !!exec->contended; 109 : } 110 : 111 : void drm_exec_init(struct drm_exec *exec, uint32_t flags); 112 : void drm_exec_fini(struct drm_exec *exec); 113 : bool drm_exec_cleanup(struct drm_exec *exec); 114 : int drm_exec_lock_obj(struct drm_exec *exec, struct drm_gem_object *obj); 115 : void drm_exec_unlock_obj(struct drm_exec *exec, struct drm_gem_object *obj); 116 : int drm_exec_prepare_obj(struct drm_exec *exec, struct drm_gem_object *obj, 117 : unsigned int num_fences); 118 : int drm_exec_prepare_array(struct drm_exec *exec, 119 : struct drm_gem_object **objects, 120 : unsigned int num_objects, 121 : unsigned int num_fences); 122 : 123 : #endif