LCOV - code coverage report
Current view: top level - include/drm - drm_modeset_lock.h (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 6 0.0 %
Date: 2022-03-28 13:20:08 Functions: 0 0 -
Branches: 0 2 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2014 Red Hat
       3                 :            :  * Author: Rob Clark <robdclark@gmail.com>
       4                 :            :  *
       5                 :            :  * Permission is hereby granted, free of charge, to any person obtaining a
       6                 :            :  * copy of this software and associated documentation files (the "Software"),
       7                 :            :  * to deal in the Software without restriction, including without limitation
       8                 :            :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       9                 :            :  * and/or sell copies of the Software, and to permit persons to whom the
      10                 :            :  * Software is furnished to do so, subject to the following conditions:
      11                 :            :  *
      12                 :            :  * The above copyright notice and this permission notice shall be included in
      13                 :            :  * all copies or substantial portions of the Software.
      14                 :            :  *
      15                 :            :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16                 :            :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17                 :            :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      18                 :            :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      19                 :            :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      20                 :            :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      21                 :            :  * OTHER DEALINGS IN THE SOFTWARE.
      22                 :            :  */
      23                 :            : 
      24                 :            : #ifndef DRM_MODESET_LOCK_H_
      25                 :            : #define DRM_MODESET_LOCK_H_
      26                 :            : 
      27                 :            : #include <linux/ww_mutex.h>
      28                 :            : 
      29                 :            : struct drm_modeset_lock;
      30                 :            : 
      31                 :            : /**
      32                 :            :  * struct drm_modeset_acquire_ctx - locking context (see ww_acquire_ctx)
      33                 :            :  * @ww_ctx: base acquire ctx
      34                 :            :  * @contended: used internally for -EDEADLK handling
      35                 :            :  * @locked: list of held locks
      36                 :            :  * @trylock_only: trylock mode used in atomic contexts/panic notifiers
      37                 :            :  * @interruptible: whether interruptible locking should be used.
      38                 :            :  *
      39                 :            :  * Each thread competing for a set of locks must use one acquire
      40                 :            :  * ctx.  And if any lock fxn returns -EDEADLK, it must backoff and
      41                 :            :  * retry.
      42                 :            :  */
      43                 :            : struct drm_modeset_acquire_ctx {
      44                 :            : 
      45                 :            :         struct ww_acquire_ctx ww_ctx;
      46                 :            : 
      47                 :            :         /*
      48                 :            :          * Contended lock: if a lock is contended you should only call
      49                 :            :          * drm_modeset_backoff() which drops locks and slow-locks the
      50                 :            :          * contended lock.
      51                 :            :          */
      52                 :            :         struct drm_modeset_lock *contended;
      53                 :            : 
      54                 :            :         /*
      55                 :            :          * list of held locks (drm_modeset_lock)
      56                 :            :          */
      57                 :            :         struct list_head locked;
      58                 :            : 
      59                 :            :         /*
      60                 :            :          * Trylock mode, use only for panic handlers!
      61                 :            :          */
      62                 :            :         bool trylock_only;
      63                 :            : 
      64                 :            :         /* Perform interruptible waits on this context. */
      65                 :            :         bool interruptible;
      66                 :            : };
      67                 :            : 
      68                 :            : /**
      69                 :            :  * struct drm_modeset_lock - used for locking modeset resources.
      70                 :            :  * @mutex: resource locking
      71                 :            :  * @head: used to hold its place on &drm_atomi_state.locked list when
      72                 :            :  *    part of an atomic update
      73                 :            :  *
      74                 :            :  * Used for locking CRTCs and other modeset resources.
      75                 :            :  */
      76                 :            : struct drm_modeset_lock {
      77                 :            :         /*
      78                 :            :          * modeset lock
      79                 :            :          */
      80                 :            :         struct ww_mutex mutex;
      81                 :            : 
      82                 :            :         /*
      83                 :            :          * Resources that are locked as part of an atomic update are added
      84                 :            :          * to a list (so we know what to unlock at the end).
      85                 :            :          */
      86                 :            :         struct list_head head;
      87                 :            : };
      88                 :            : 
      89                 :            : #define DRM_MODESET_ACQUIRE_INTERRUPTIBLE BIT(0)
      90                 :            : 
      91                 :            : void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx,
      92                 :            :                 uint32_t flags);
      93                 :            : void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx);
      94                 :            : void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx);
      95                 :            : int drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx);
      96                 :            : 
      97                 :            : void drm_modeset_lock_init(struct drm_modeset_lock *lock);
      98                 :            : 
      99                 :            : /**
     100                 :            :  * drm_modeset_lock_fini - cleanup lock
     101                 :            :  * @lock: lock to cleanup
     102                 :            :  */
     103                 :          0 : static inline void drm_modeset_lock_fini(struct drm_modeset_lock *lock)
     104                 :            : {
     105         [ #  # ]:          0 :         WARN_ON(!list_empty(&lock->head));
     106                 :            : }
     107                 :            : 
     108                 :            : /**
     109                 :            :  * drm_modeset_is_locked - equivalent to mutex_is_locked()
     110                 :            :  * @lock: lock to check
     111                 :            :  */
     112                 :          0 : static inline bool drm_modeset_is_locked(struct drm_modeset_lock *lock)
     113                 :            : {
     114                 :          0 :         return ww_mutex_is_locked(&lock->mutex);
     115                 :            : }
     116                 :            : 
     117                 :            : /**
     118                 :            :  * drm_modeset_lock_assert_held - equivalent to lockdep_assert_held()
     119                 :            :  * @lock: lock to check
     120                 :            :  */
     121                 :          0 : static inline void drm_modeset_lock_assert_held(struct drm_modeset_lock *lock)
     122                 :            : {
     123                 :          0 :         lockdep_assert_held(&lock->mutex.base);
     124                 :            : }
     125                 :            : 
     126                 :            : int drm_modeset_lock(struct drm_modeset_lock *lock,
     127                 :            :                 struct drm_modeset_acquire_ctx *ctx);
     128                 :            : int __must_check drm_modeset_lock_single_interruptible(struct drm_modeset_lock *lock);
     129                 :            : void drm_modeset_unlock(struct drm_modeset_lock *lock);
     130                 :            : 
     131                 :            : struct drm_device;
     132                 :            : struct drm_crtc;
     133                 :            : struct drm_plane;
     134                 :            : 
     135                 :            : void drm_modeset_lock_all(struct drm_device *dev);
     136                 :            : void drm_modeset_unlock_all(struct drm_device *dev);
     137                 :            : void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
     138                 :            : 
     139                 :            : int drm_modeset_lock_all_ctx(struct drm_device *dev,
     140                 :            :                              struct drm_modeset_acquire_ctx *ctx);
     141                 :            : 
     142                 :            : /**
     143                 :            :  * DRM_MODESET_LOCK_ALL_BEGIN - Helper to acquire modeset locks
     144                 :            :  * @dev: drm device
     145                 :            :  * @ctx: local modeset acquire context, will be dereferenced
     146                 :            :  * @flags: DRM_MODESET_ACQUIRE_* flags to pass to drm_modeset_acquire_init()
     147                 :            :  * @ret: local ret/err/etc variable to track error status
     148                 :            :  *
     149                 :            :  * Use these macros to simplify grabbing all modeset locks using a local
     150                 :            :  * context. This has the advantage of reducing boilerplate, but also properly
     151                 :            :  * checking return values where appropriate.
     152                 :            :  *
     153                 :            :  * Any code run between BEGIN and END will be holding the modeset locks.
     154                 :            :  *
     155                 :            :  * This must be paired with DRM_MODESET_LOCK_ALL_END(). We will jump back and
     156                 :            :  * forth between the labels on deadlock and error conditions.
     157                 :            :  *
     158                 :            :  * Drivers can acquire additional modeset locks. If any lock acquisition
     159                 :            :  * fails, the control flow needs to jump to DRM_MODESET_LOCK_ALL_END() with
     160                 :            :  * the @ret parameter containing the return value of drm_modeset_lock().
     161                 :            :  *
     162                 :            :  * Returns:
     163                 :            :  * The only possible value of ret immediately after DRM_MODESET_LOCK_ALL_BEGIN()
     164                 :            :  * is 0, so no error checking is necessary
     165                 :            :  */
     166                 :            : #define DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, flags, ret)                \
     167                 :            :         drm_modeset_acquire_init(&ctx, flags);                              \
     168                 :            : modeset_lock_retry:                                                     \
     169                 :            :         ret = drm_modeset_lock_all_ctx(dev, &ctx);                  \
     170                 :            :         if (ret)                                                        \
     171                 :            :                 goto modeset_lock_fail;
     172                 :            : 
     173                 :            : /**
     174                 :            :  * DRM_MODESET_LOCK_ALL_END - Helper to release and cleanup modeset locks
     175                 :            :  * @ctx: local modeset acquire context, will be dereferenced
     176                 :            :  * @ret: local ret/err/etc variable to track error status
     177                 :            :  *
     178                 :            :  * The other side of DRM_MODESET_LOCK_ALL_BEGIN(). It will bounce back to BEGIN
     179                 :            :  * if ret is -EDEADLK.
     180                 :            :  *
     181                 :            :  * It's important that you use the same ret variable for begin and end so
     182                 :            :  * deadlock conditions are properly handled.
     183                 :            :  *
     184                 :            :  * Returns:
     185                 :            :  * ret will be untouched unless it is -EDEADLK on entry. That means that if you
     186                 :            :  * successfully acquire the locks, ret will be whatever your code sets it to. If
     187                 :            :  * there is a deadlock or other failure with acquire or backoff, ret will be set
     188                 :            :  * to that failure. In both of these cases the code between BEGIN/END will not
     189                 :            :  * be run, so the failure will reflect the inability to grab the locks.
     190                 :            :  */
     191                 :            : #define DRM_MODESET_LOCK_ALL_END(ctx, ret)                              \
     192                 :            : modeset_lock_fail:                                                      \
     193                 :            :         if (ret == -EDEADLK) {                                          \
     194                 :            :                 ret = drm_modeset_backoff(&ctx);                    \
     195                 :            :                 if (!ret)                                               \
     196                 :            :                         goto modeset_lock_retry;                        \
     197                 :            :         }                                                               \
     198                 :            :         drm_modeset_drop_locks(&ctx);                                       \
     199                 :            :         drm_modeset_acquire_fini(&ctx);
     200                 :            : 
     201                 :            : #endif /* DRM_MODESET_LOCK_H_ */

Generated by: LCOV version 1.14