.. | .. |
---|
68 | 68 | /** |
---|
69 | 69 | * struct drm_modeset_lock - used for locking modeset resources. |
---|
70 | 70 | * @mutex: resource locking |
---|
71 | | - * @head: used to hold it's place on &drm_atomi_state.locked list when |
---|
| 71 | + * @head: used to hold its place on &drm_atomi_state.locked list when |
---|
72 | 72 | * part of an atomic update |
---|
73 | 73 | * |
---|
74 | 74 | * Used for locking CRTCs and other modeset resources. |
---|
.. | .. |
---|
114 | 114 | return ww_mutex_is_locked(&lock->mutex); |
---|
115 | 115 | } |
---|
116 | 116 | |
---|
| 117 | +/** |
---|
| 118 | + * drm_modeset_lock_assert_held - equivalent to lockdep_assert_held() |
---|
| 119 | + * @lock: lock to check |
---|
| 120 | + */ |
---|
| 121 | +static inline void drm_modeset_lock_assert_held(struct drm_modeset_lock *lock) |
---|
| 122 | +{ |
---|
| 123 | + lockdep_assert_held(&lock->mutex.base); |
---|
| 124 | +} |
---|
| 125 | + |
---|
117 | 126 | int drm_modeset_lock(struct drm_modeset_lock *lock, |
---|
118 | 127 | struct drm_modeset_acquire_ctx *ctx); |
---|
119 | 128 | int __must_check drm_modeset_lock_single_interruptible(struct drm_modeset_lock *lock); |
---|
.. | .. |
---|
130 | 139 | int drm_modeset_lock_all_ctx(struct drm_device *dev, |
---|
131 | 140 | struct drm_modeset_acquire_ctx *ctx); |
---|
132 | 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 | + if (!drm_drv_uses_atomic_modeset(dev)) \ |
---|
| 168 | + mutex_lock(&dev->mode_config.mutex); \ |
---|
| 169 | + drm_modeset_acquire_init(&ctx, flags); \ |
---|
| 170 | +modeset_lock_retry: \ |
---|
| 171 | + ret = drm_modeset_lock_all_ctx(dev, &ctx); \ |
---|
| 172 | + if (ret) \ |
---|
| 173 | + goto modeset_lock_fail; |
---|
| 174 | + |
---|
| 175 | +/** |
---|
| 176 | + * DRM_MODESET_LOCK_ALL_END - Helper to release and cleanup modeset locks |
---|
| 177 | + * @dev: drm device |
---|
| 178 | + * @ctx: local modeset acquire context, will be dereferenced |
---|
| 179 | + * @ret: local ret/err/etc variable to track error status |
---|
| 180 | + * |
---|
| 181 | + * The other side of DRM_MODESET_LOCK_ALL_BEGIN(). It will bounce back to BEGIN |
---|
| 182 | + * if ret is -EDEADLK. |
---|
| 183 | + * |
---|
| 184 | + * It's important that you use the same ret variable for begin and end so |
---|
| 185 | + * deadlock conditions are properly handled. |
---|
| 186 | + * |
---|
| 187 | + * Returns: |
---|
| 188 | + * ret will be untouched unless it is -EDEADLK on entry. That means that if you |
---|
| 189 | + * successfully acquire the locks, ret will be whatever your code sets it to. If |
---|
| 190 | + * there is a deadlock or other failure with acquire or backoff, ret will be set |
---|
| 191 | + * to that failure. In both of these cases the code between BEGIN/END will not |
---|
| 192 | + * be run, so the failure will reflect the inability to grab the locks. |
---|
| 193 | + */ |
---|
| 194 | +#define DRM_MODESET_LOCK_ALL_END(dev, ctx, ret) \ |
---|
| 195 | +modeset_lock_fail: \ |
---|
| 196 | + if (ret == -EDEADLK) { \ |
---|
| 197 | + ret = drm_modeset_backoff(&ctx); \ |
---|
| 198 | + if (!ret) \ |
---|
| 199 | + goto modeset_lock_retry; \ |
---|
| 200 | + } \ |
---|
| 201 | + drm_modeset_drop_locks(&ctx); \ |
---|
| 202 | + drm_modeset_acquire_fini(&ctx); \ |
---|
| 203 | + if (!drm_drv_uses_atomic_modeset(dev)) \ |
---|
| 204 | + mutex_unlock(&dev->mode_config.mutex); |
---|
| 205 | + |
---|
133 | 206 | #endif /* DRM_MODESET_LOCK_H_ */ |
---|