2022-04-07 09:17:51 +03:00
/* SPDX-License-Identifier: GPL-2.0 OR MIT */
# ifndef __DRM_EXEC_H__
# define __DRM_EXEC_H__
2023-07-31 15:36:24 +03:00
# include <linux/compiler.h>
2022-04-07 09:17:51 +03:00
# include <linux/ww_mutex.h>
# define DRM_EXEC_INTERRUPTIBLE_WAIT BIT(0)
# define DRM_EXEC_IGNORE_DUPLICATES BIT(1)
struct drm_gem_object ;
/**
* struct drm_exec - Execution context
*/
struct drm_exec {
/**
* @ flags : Flags to control locking behavior
*/
uint32_t flags ;
/**
* @ ticket : WW ticket used for acquiring locks
*/
struct ww_acquire_ctx ticket ;
/**
* @ num_objects : number of objects locked
*/
unsigned int num_objects ;
/**
* @ max_objects : maximum objects in array
*/
unsigned int max_objects ;
/**
* @ objects : array of the locked objects
*/
struct drm_gem_object * * objects ;
/**
* @ contended : contended GEM object we backed off for
*/
struct drm_gem_object * contended ;
/**
* @ prelocked : already locked GEM object due to contention
*/
struct drm_gem_object * prelocked ;
} ;
2023-09-06 12:50:39 +03:00
/**
* drm_exec_obj ( ) - Return the object for a give drm_exec index
* @ exec : Pointer to the drm_exec context
* @ index : The index .
*
* Return : Pointer to the locked object corresponding to @ index if
* index is within the number of locked objects . NULL otherwise .
*/
static inline struct drm_gem_object *
drm_exec_obj ( struct drm_exec * exec , unsigned long index )
{
return index < exec - > num_objects ? exec - > objects [ index ] : NULL ;
}
2022-04-07 09:17:51 +03:00
/**
* drm_exec_for_each_locked_object - iterate over all the locked objects
* @ exec : drm_exec object
* @ index : unsigned long index for the iteration
* @ obj : the current GEM object
*
* Iterate over all the locked GEM objects inside the drm_exec object .
*/
2023-09-06 12:50:39 +03:00
# define drm_exec_for_each_locked_object(exec, index, obj) \
for ( ( index ) = 0 ; ( ( obj ) = drm_exec_obj ( exec , index ) ) ; + + ( index ) )
/**
* drm_exec_for_each_locked_object_reverse - iterate over all the locked
* objects in reverse locking order
* @ exec : drm_exec object
* @ index : unsigned long index for the iteration
* @ obj : the current GEM object
*
* Iterate over all the locked GEM objects inside the drm_exec object in
* reverse locking order . Note that @ index may go below zero and wrap ,
* but that will be caught by drm_exec_obj ( ) , returning a NULL object .
*/
# define drm_exec_for_each_locked_object_reverse(exec, index, obj) \
for ( ( index ) = ( exec ) - > num_objects - 1 ; \
( ( obj ) = drm_exec_obj ( exec , index ) ) ; - - ( index ) )
2022-04-07 09:17:51 +03:00
/**
* drm_exec_until_all_locked - loop until all GEM objects are locked
* @ exec : drm_exec object
*
* Core functionality of the drm_exec object . Loops until all GEM objects are
* locked and no more contention exists . At the beginning of the loop it is
* guaranteed that no GEM object is locked .
*
* Since labels can ' t be defined local to the loops body we use a jump pointer
* to make sure that the retry is only used from within the loops body .
*/
2023-07-31 15:36:24 +03:00
# define drm_exec_until_all_locked(exec) \
__PASTE ( __drm_exec_ , __LINE__ ) : \
for ( void * __drm_exec_retry_ptr ; ( { \
__drm_exec_retry_ptr = & & __PASTE ( __drm_exec_ , __LINE__ ) ; \
( void ) __drm_exec_retry_ptr ; \
drm_exec_cleanup ( exec ) ; \
2022-04-07 09:17:51 +03:00
} ) ; )
/**
* drm_exec_retry_on_contention - restart the loop to grap all locks
* @ exec : drm_exec object
*
* Control flow helper to continue when a contention was detected and we need to
* clean up and re - start the loop to prepare all GEM objects .
*/
# define drm_exec_retry_on_contention(exec) \
do { \
if ( unlikely ( drm_exec_is_contended ( exec ) ) ) \
goto * __drm_exec_retry_ptr ; \
} while ( 0 )
/**
* drm_exec_is_contended - check for contention
* @ exec : drm_exec object
*
* Returns true if the drm_exec object has run into some contention while
* locking a GEM object and needs to clean up .
*/
static inline bool drm_exec_is_contended ( struct drm_exec * exec )
{
return ! ! exec - > contended ;
}
void drm_exec_init ( struct drm_exec * exec , uint32_t flags ) ;
void drm_exec_fini ( struct drm_exec * exec ) ;
bool drm_exec_cleanup ( struct drm_exec * exec ) ;
int drm_exec_lock_obj ( struct drm_exec * exec , struct drm_gem_object * obj ) ;
void drm_exec_unlock_obj ( struct drm_exec * exec , struct drm_gem_object * obj ) ;
int drm_exec_prepare_obj ( struct drm_exec * exec , struct drm_gem_object * obj ,
unsigned int num_fences ) ;
int drm_exec_prepare_array ( struct drm_exec * exec ,
struct drm_gem_object * * objects ,
unsigned int num_objects ,
unsigned int num_fences ) ;
# endif