109593216SChristian König /* SPDX-License-Identifier: GPL-2.0 OR MIT */
209593216SChristian König
309593216SChristian König #ifndef __DRM_EXEC_H__
409593216SChristian König #define __DRM_EXEC_H__
509593216SChristian König
6616bceaeSChristian König #include <linux/compiler.h>
709593216SChristian König #include <linux/ww_mutex.h>
809593216SChristian König
909593216SChristian König #define DRM_EXEC_INTERRUPTIBLE_WAIT BIT(0)
1009593216SChristian König #define DRM_EXEC_IGNORE_DUPLICATES BIT(1)
1109593216SChristian König
1209593216SChristian König struct drm_gem_object;
1309593216SChristian König
1409593216SChristian König /**
1509593216SChristian König * struct drm_exec - Execution context
1609593216SChristian König */
1709593216SChristian König struct drm_exec {
1809593216SChristian König /**
1909593216SChristian König * @flags: Flags to control locking behavior
2009593216SChristian König */
2109593216SChristian König uint32_t flags;
2209593216SChristian König
2309593216SChristian König /**
2409593216SChristian König * @ticket: WW ticket used for acquiring locks
2509593216SChristian König */
2609593216SChristian König struct ww_acquire_ctx ticket;
2709593216SChristian König
2809593216SChristian König /**
2909593216SChristian König * @num_objects: number of objects locked
3009593216SChristian König */
3109593216SChristian König unsigned int num_objects;
3209593216SChristian König
3309593216SChristian König /**
3409593216SChristian König * @max_objects: maximum objects in array
3509593216SChristian König */
3609593216SChristian König unsigned int max_objects;
3709593216SChristian König
3809593216SChristian König /**
3909593216SChristian König * @objects: array of the locked objects
4009593216SChristian König */
4109593216SChristian König struct drm_gem_object **objects;
4209593216SChristian König
4309593216SChristian König /**
4409593216SChristian König * @contended: contended GEM object we backed off for
4509593216SChristian König */
4609593216SChristian König struct drm_gem_object *contended;
4709593216SChristian König
4809593216SChristian König /**
4909593216SChristian König * @prelocked: already locked GEM object due to contention
5009593216SChristian König */
5109593216SChristian König struct drm_gem_object *prelocked;
5209593216SChristian König };
5309593216SChristian König
5409593216SChristian König /**
55*d20b484cSThomas Hellström * drm_exec_obj() - Return the object for a give drm_exec index
56*d20b484cSThomas Hellström * @exec: Pointer to the drm_exec context
57*d20b484cSThomas Hellström * @index: The index.
58*d20b484cSThomas Hellström *
59*d20b484cSThomas Hellström * Return: Pointer to the locked object corresponding to @index if
60*d20b484cSThomas Hellström * index is within the number of locked objects. NULL otherwise.
61*d20b484cSThomas Hellström */
62*d20b484cSThomas Hellström static inline struct drm_gem_object *
drm_exec_obj(struct drm_exec * exec,unsigned long index)63*d20b484cSThomas Hellström drm_exec_obj(struct drm_exec *exec, unsigned long index)
64*d20b484cSThomas Hellström {
65*d20b484cSThomas Hellström return index < exec->num_objects ? exec->objects[index] : NULL;
66*d20b484cSThomas Hellström }
67*d20b484cSThomas Hellström
68*d20b484cSThomas Hellström /**
6909593216SChristian König * drm_exec_for_each_locked_object - iterate over all the locked objects
7009593216SChristian König * @exec: drm_exec object
7109593216SChristian König * @index: unsigned long index for the iteration
7209593216SChristian König * @obj: the current GEM object
7309593216SChristian König *
7409593216SChristian König * Iterate over all the locked GEM objects inside the drm_exec object.
7509593216SChristian König */
7609593216SChristian König #define drm_exec_for_each_locked_object(exec, index, obj) \
77*d20b484cSThomas Hellström for ((index) = 0; ((obj) = drm_exec_obj(exec, index)); ++(index))
78*d20b484cSThomas Hellström
79*d20b484cSThomas Hellström /**
80*d20b484cSThomas Hellström * drm_exec_for_each_locked_object_reverse - iterate over all the locked
81*d20b484cSThomas Hellström * objects in reverse locking order
82*d20b484cSThomas Hellström * @exec: drm_exec object
83*d20b484cSThomas Hellström * @index: unsigned long index for the iteration
84*d20b484cSThomas Hellström * @obj: the current GEM object
85*d20b484cSThomas Hellström *
86*d20b484cSThomas Hellström * Iterate over all the locked GEM objects inside the drm_exec object in
87*d20b484cSThomas Hellström * reverse locking order. Note that @index may go below zero and wrap,
88*d20b484cSThomas Hellström * but that will be caught by drm_exec_obj(), returning a NULL object.
89*d20b484cSThomas Hellström */
90*d20b484cSThomas Hellström #define drm_exec_for_each_locked_object_reverse(exec, index, obj) \
91*d20b484cSThomas Hellström for ((index) = (exec)->num_objects - 1; \
92*d20b484cSThomas Hellström ((obj) = drm_exec_obj(exec, index)); --(index))
9309593216SChristian König
9409593216SChristian König /**
9509593216SChristian König * drm_exec_until_all_locked - loop until all GEM objects are locked
9609593216SChristian König * @exec: drm_exec object
9709593216SChristian König *
9809593216SChristian König * Core functionality of the drm_exec object. Loops until all GEM objects are
9909593216SChristian König * locked and no more contention exists. At the beginning of the loop it is
10009593216SChristian König * guaranteed that no GEM object is locked.
10109593216SChristian König *
10209593216SChristian König * Since labels can't be defined local to the loops body we use a jump pointer
10309593216SChristian König * to make sure that the retry is only used from within the loops body.
10409593216SChristian König */
10509593216SChristian König #define drm_exec_until_all_locked(exec) \
106616bceaeSChristian König __PASTE(__drm_exec_, __LINE__): \
10709593216SChristian König for (void *__drm_exec_retry_ptr; ({ \
108616bceaeSChristian König __drm_exec_retry_ptr = &&__PASTE(__drm_exec_, __LINE__);\
10909593216SChristian König (void)__drm_exec_retry_ptr; \
11009593216SChristian König drm_exec_cleanup(exec); \
11109593216SChristian König });)
11209593216SChristian König
11309593216SChristian König /**
11409593216SChristian König * drm_exec_retry_on_contention - restart the loop to grap all locks
11509593216SChristian König * @exec: drm_exec object
11609593216SChristian König *
11709593216SChristian König * Control flow helper to continue when a contention was detected and we need to
11809593216SChristian König * clean up and re-start the loop to prepare all GEM objects.
11909593216SChristian König */
12009593216SChristian König #define drm_exec_retry_on_contention(exec) \
12109593216SChristian König do { \
12209593216SChristian König if (unlikely(drm_exec_is_contended(exec))) \
12309593216SChristian König goto *__drm_exec_retry_ptr; \
12409593216SChristian König } while (0)
12509593216SChristian König
12609593216SChristian König /**
12709593216SChristian König * drm_exec_is_contended - check for contention
12809593216SChristian König * @exec: drm_exec object
12909593216SChristian König *
13009593216SChristian König * Returns true if the drm_exec object has run into some contention while
13109593216SChristian König * locking a GEM object and needs to clean up.
13209593216SChristian König */
drm_exec_is_contended(struct drm_exec * exec)13309593216SChristian König static inline bool drm_exec_is_contended(struct drm_exec *exec)
13409593216SChristian König {
13509593216SChristian König return !!exec->contended;
13609593216SChristian König }
13709593216SChristian König
13809593216SChristian König void drm_exec_init(struct drm_exec *exec, uint32_t flags);
13909593216SChristian König void drm_exec_fini(struct drm_exec *exec);
14009593216SChristian König bool drm_exec_cleanup(struct drm_exec *exec);
14109593216SChristian König int drm_exec_lock_obj(struct drm_exec *exec, struct drm_gem_object *obj);
14209593216SChristian König void drm_exec_unlock_obj(struct drm_exec *exec, struct drm_gem_object *obj);
14309593216SChristian König int drm_exec_prepare_obj(struct drm_exec *exec, struct drm_gem_object *obj,
14409593216SChristian König unsigned int num_fences);
14509593216SChristian König int drm_exec_prepare_array(struct drm_exec *exec,
14609593216SChristian König struct drm_gem_object **objects,
14709593216SChristian König unsigned int num_objects,
14809593216SChristian König unsigned int num_fences);
14909593216SChristian König
15009593216SChristian König #endif
151