xref: /openbmc/linux/include/drm/drm_exec.h (revision 5804c19b80bf625c6a9925317f845e497434d6d3)
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