![]() |
|
|||
0001 /* 0002 * Copyright (C) 2014 Red Hat 0003 * Author: Rob Clark <robdclark@gmail.com> 0004 * 0005 * Permission is hereby granted, free of charge, to any person obtaining a 0006 * copy of this software and associated documentation files (the "Software"), 0007 * to deal in the Software without restriction, including without limitation 0008 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 0009 * and/or sell copies of the Software, and to permit persons to whom the 0010 * Software is furnished to do so, subject to the following conditions: 0011 * 0012 * The above copyright notice and this permission notice shall be included in 0013 * all copies or substantial portions of the Software. 0014 * 0015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 0018 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 0019 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 0020 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 0021 * OTHER DEALINGS IN THE SOFTWARE. 0022 */ 0023 0024 #ifndef DRM_MODESET_LOCK_H_ 0025 #define DRM_MODESET_LOCK_H_ 0026 0027 #include <linux/types.h> /* stackdepot.h is not self-contained */ 0028 #include <linux/stackdepot.h> 0029 #include <linux/ww_mutex.h> 0030 0031 struct drm_modeset_lock; 0032 0033 /** 0034 * struct drm_modeset_acquire_ctx - locking context (see ww_acquire_ctx) 0035 * @ww_ctx: base acquire ctx 0036 * @contended: used internally for -EDEADLK handling 0037 * @stack_depot: used internally for contention debugging 0038 * @locked: list of held locks 0039 * @trylock_only: trylock mode used in atomic contexts/panic notifiers 0040 * @interruptible: whether interruptible locking should be used. 0041 * 0042 * Each thread competing for a set of locks must use one acquire 0043 * ctx. And if any lock fxn returns -EDEADLK, it must backoff and 0044 * retry. 0045 */ 0046 struct drm_modeset_acquire_ctx { 0047 0048 struct ww_acquire_ctx ww_ctx; 0049 0050 /* 0051 * Contended lock: if a lock is contended you should only call 0052 * drm_modeset_backoff() which drops locks and slow-locks the 0053 * contended lock. 0054 */ 0055 struct drm_modeset_lock *contended; 0056 0057 /* 0058 * Stack depot for debugging when a contended lock was not backed off 0059 * from. 0060 */ 0061 depot_stack_handle_t stack_depot; 0062 0063 /* 0064 * list of held locks (drm_modeset_lock) 0065 */ 0066 struct list_head locked; 0067 0068 /* 0069 * Trylock mode, use only for panic handlers! 0070 */ 0071 bool trylock_only; 0072 0073 /* Perform interruptible waits on this context. */ 0074 bool interruptible; 0075 }; 0076 0077 /** 0078 * struct drm_modeset_lock - used for locking modeset resources. 0079 * @mutex: resource locking 0080 * @head: used to hold its place on &drm_atomi_state.locked list when 0081 * part of an atomic update 0082 * 0083 * Used for locking CRTCs and other modeset resources. 0084 */ 0085 struct drm_modeset_lock { 0086 /* 0087 * modeset lock 0088 */ 0089 struct ww_mutex mutex; 0090 0091 /* 0092 * Resources that are locked as part of an atomic update are added 0093 * to a list (so we know what to unlock at the end). 0094 */ 0095 struct list_head head; 0096 }; 0097 0098 #define DRM_MODESET_ACQUIRE_INTERRUPTIBLE BIT(0) 0099 0100 void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx, 0101 uint32_t flags); 0102 void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx); 0103 void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx); 0104 int drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx); 0105 0106 void drm_modeset_lock_init(struct drm_modeset_lock *lock); 0107 0108 /** 0109 * drm_modeset_lock_fini - cleanup lock 0110 * @lock: lock to cleanup 0111 */ 0112 static inline void drm_modeset_lock_fini(struct drm_modeset_lock *lock) 0113 { 0114 WARN_ON(!list_empty(&lock->head)); 0115 } 0116 0117 /** 0118 * drm_modeset_is_locked - equivalent to mutex_is_locked() 0119 * @lock: lock to check 0120 */ 0121 static inline bool drm_modeset_is_locked(struct drm_modeset_lock *lock) 0122 { 0123 return ww_mutex_is_locked(&lock->mutex); 0124 } 0125 0126 /** 0127 * drm_modeset_lock_assert_held - equivalent to lockdep_assert_held() 0128 * @lock: lock to check 0129 */ 0130 static inline void drm_modeset_lock_assert_held(struct drm_modeset_lock *lock) 0131 { 0132 lockdep_assert_held(&lock->mutex.base); 0133 } 0134 0135 int drm_modeset_lock(struct drm_modeset_lock *lock, 0136 struct drm_modeset_acquire_ctx *ctx); 0137 int __must_check drm_modeset_lock_single_interruptible(struct drm_modeset_lock *lock); 0138 void drm_modeset_unlock(struct drm_modeset_lock *lock); 0139 0140 struct drm_device; 0141 struct drm_crtc; 0142 struct drm_plane; 0143 0144 void drm_modeset_lock_all(struct drm_device *dev); 0145 void drm_modeset_unlock_all(struct drm_device *dev); 0146 void drm_warn_on_modeset_not_all_locked(struct drm_device *dev); 0147 0148 int drm_modeset_lock_all_ctx(struct drm_device *dev, 0149 struct drm_modeset_acquire_ctx *ctx); 0150 0151 /** 0152 * DRM_MODESET_LOCK_ALL_BEGIN - Helper to acquire modeset locks 0153 * @dev: drm device 0154 * @ctx: local modeset acquire context, will be dereferenced 0155 * @flags: DRM_MODESET_ACQUIRE_* flags to pass to drm_modeset_acquire_init() 0156 * @ret: local ret/err/etc variable to track error status 0157 * 0158 * Use these macros to simplify grabbing all modeset locks using a local 0159 * context. This has the advantage of reducing boilerplate, but also properly 0160 * checking return values where appropriate. 0161 * 0162 * Any code run between BEGIN and END will be holding the modeset locks. 0163 * 0164 * This must be paired with DRM_MODESET_LOCK_ALL_END(). We will jump back and 0165 * forth between the labels on deadlock and error conditions. 0166 * 0167 * Drivers can acquire additional modeset locks. If any lock acquisition 0168 * fails, the control flow needs to jump to DRM_MODESET_LOCK_ALL_END() with 0169 * the @ret parameter containing the return value of drm_modeset_lock(). 0170 * 0171 * Returns: 0172 * The only possible value of ret immediately after DRM_MODESET_LOCK_ALL_BEGIN() 0173 * is 0, so no error checking is necessary 0174 */ 0175 #define DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, flags, ret) \ 0176 if (!drm_drv_uses_atomic_modeset(dev)) \ 0177 mutex_lock(&dev->mode_config.mutex); \ 0178 drm_modeset_acquire_init(&ctx, flags); \ 0179 modeset_lock_retry: \ 0180 ret = drm_modeset_lock_all_ctx(dev, &ctx); \ 0181 if (ret) \ 0182 goto modeset_lock_fail; 0183 0184 /** 0185 * DRM_MODESET_LOCK_ALL_END - Helper to release and cleanup modeset locks 0186 * @dev: drm device 0187 * @ctx: local modeset acquire context, will be dereferenced 0188 * @ret: local ret/err/etc variable to track error status 0189 * 0190 * The other side of DRM_MODESET_LOCK_ALL_BEGIN(). It will bounce back to BEGIN 0191 * if ret is -EDEADLK. 0192 * 0193 * It's important that you use the same ret variable for begin and end so 0194 * deadlock conditions are properly handled. 0195 * 0196 * Returns: 0197 * ret will be untouched unless it is -EDEADLK on entry. That means that if you 0198 * successfully acquire the locks, ret will be whatever your code sets it to. If 0199 * there is a deadlock or other failure with acquire or backoff, ret will be set 0200 * to that failure. In both of these cases the code between BEGIN/END will not 0201 * be run, so the failure will reflect the inability to grab the locks. 0202 */ 0203 #define DRM_MODESET_LOCK_ALL_END(dev, ctx, ret) \ 0204 modeset_lock_fail: \ 0205 if (ret == -EDEADLK) { \ 0206 ret = drm_modeset_backoff(&ctx); \ 0207 if (!ret) \ 0208 goto modeset_lock_retry; \ 0209 } \ 0210 drm_modeset_drop_locks(&ctx); \ 0211 drm_modeset_acquire_fini(&ctx); \ 0212 if (!drm_drv_uses_atomic_modeset(dev)) \ 0213 mutex_unlock(&dev->mode_config.mutex); 0214 0215 #endif /* DRM_MODESET_LOCK_H_ */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |