1 1.5 riastrad /* $NetBSD: drm_modeset_lock.c,v 1.5 2021/12/18 23:44:57 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright (C) 2014 Red Hat 5 1.1 riastrad * Author: Rob Clark <robdclark (at) gmail.com> 6 1.1 riastrad * 7 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 8 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 9 1.1 riastrad * to deal in the Software without restriction, including without limitation 10 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 12 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 13 1.1 riastrad * 14 1.1 riastrad * The above copyright notice and this permission notice shall be included in 15 1.1 riastrad * all copies or substantial portions of the Software. 16 1.1 riastrad * 17 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 1.1 riastrad * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 1.1 riastrad * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 1.1 riastrad * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 1.1 riastrad * OTHER DEALINGS IN THE SOFTWARE. 24 1.1 riastrad */ 25 1.1 riastrad 26 1.1 riastrad #include <sys/cdefs.h> 27 1.5 riastrad __KERNEL_RCSID(0, "$NetBSD: drm_modeset_lock.c,v 1.5 2021/12/18 23:44:57 riastradh Exp $"); 28 1.3 riastrad 29 1.5 riastrad #include <drm/drm_atomic.h> 30 1.1 riastrad #include <drm/drm_crtc.h> 31 1.5 riastrad #include <drm/drm_device.h> 32 1.1 riastrad #include <drm/drm_modeset_lock.h> 33 1.1 riastrad 34 1.1 riastrad /** 35 1.1 riastrad * DOC: kms locking 36 1.1 riastrad * 37 1.1 riastrad * As KMS moves toward more fine grained locking, and atomic ioctl where 38 1.1 riastrad * userspace can indirectly control locking order, it becomes necessary 39 1.5 riastrad * to use &ww_mutex and acquire-contexts to avoid deadlocks. But because 40 1.1 riastrad * the locking is more distributed around the driver code, we want a bit 41 1.1 riastrad * of extra utility/tracking out of our acquire-ctx. This is provided 42 1.5 riastrad * by &struct drm_modeset_lock and &struct drm_modeset_acquire_ctx. 43 1.1 riastrad * 44 1.5 riastrad * For basic principles of &ww_mutex, see: Documentation/locking/ww-mutex-design.rst 45 1.1 riastrad * 46 1.5 riastrad * The basic usage pattern is to:: 47 1.1 riastrad * 48 1.5 riastrad * drm_modeset_acquire_init(ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE) 49 1.5 riastrad * retry: 50 1.1 riastrad * foreach (lock in random_ordered_set_of_locks) { 51 1.5 riastrad * ret = drm_modeset_lock(lock, ctx) 52 1.5 riastrad * if (ret == -EDEADLK) { 53 1.5 riastrad * ret = drm_modeset_backoff(ctx); 54 1.5 riastrad * if (!ret) 55 1.5 riastrad * goto retry; 56 1.5 riastrad * } 57 1.5 riastrad * if (ret) 58 1.5 riastrad * goto out; 59 1.1 riastrad * } 60 1.5 riastrad * ... do stuff ... 61 1.5 riastrad * out: 62 1.5 riastrad * drm_modeset_drop_locks(ctx); 63 1.5 riastrad * drm_modeset_acquire_fini(ctx); 64 1.5 riastrad * 65 1.5 riastrad * For convenience this control flow is implemented in 66 1.5 riastrad * DRM_MODESET_LOCK_ALL_BEGIN() and DRM_MODESET_LOCK_ALL_END() for the case 67 1.5 riastrad * where all modeset locks need to be taken through drm_modeset_lock_all_ctx(). 68 1.1 riastrad * 69 1.5 riastrad * If all that is needed is a single modeset lock, then the &struct 70 1.5 riastrad * drm_modeset_acquire_ctx is not needed and the locking can be simplified 71 1.5 riastrad * by passing a NULL instead of ctx in the drm_modeset_lock() call or 72 1.5 riastrad * calling drm_modeset_lock_single_interruptible(). To unlock afterwards 73 1.5 riastrad * call drm_modeset_unlock(). 74 1.5 riastrad * 75 1.5 riastrad * On top of these per-object locks using &ww_mutex there's also an overall 76 1.5 riastrad * &drm_mode_config.mutex, for protecting everything else. Mostly this means 77 1.5 riastrad * probe state of connectors, and preventing hotplug add/removal of connectors. 78 1.1 riastrad * 79 1.5 riastrad * Finally there's a bunch of dedicated locks to protect drm core internal 80 1.5 riastrad * lists and lookup data structures. 81 1.1 riastrad */ 82 1.1 riastrad 83 1.5 riastrad static DEFINE_WW_CLASS(crtc_ww_class); 84 1.5 riastrad 85 1.1 riastrad /** 86 1.1 riastrad * drm_modeset_lock_all - take all modeset locks 87 1.5 riastrad * @dev: DRM device 88 1.1 riastrad * 89 1.1 riastrad * This function takes all modeset locks, suitable where a more fine-grained 90 1.5 riastrad * scheme isn't (yet) implemented. Locks must be dropped by calling the 91 1.5 riastrad * drm_modeset_unlock_all() function. 92 1.5 riastrad * 93 1.5 riastrad * This function is deprecated. It allocates a lock acquisition context and 94 1.5 riastrad * stores it in &drm_device.mode_config. This facilitate conversion of 95 1.5 riastrad * existing code because it removes the need to manually deal with the 96 1.5 riastrad * acquisition context, but it is also brittle because the context is global 97 1.5 riastrad * and care must be taken not to nest calls. New code should use the 98 1.5 riastrad * drm_modeset_lock_all_ctx() function and pass in the context explicitly. 99 1.1 riastrad */ 100 1.1 riastrad void drm_modeset_lock_all(struct drm_device *dev) 101 1.1 riastrad { 102 1.1 riastrad struct drm_mode_config *config = &dev->mode_config; 103 1.1 riastrad struct drm_modeset_acquire_ctx *ctx; 104 1.1 riastrad int ret; 105 1.1 riastrad 106 1.1 riastrad ctx = kzalloc(sizeof(*ctx), GFP_KERNEL | __GFP_NOFAIL); 107 1.1 riastrad if (WARN_ON(!ctx)) 108 1.1 riastrad return; 109 1.1 riastrad 110 1.1 riastrad mutex_lock(&config->mutex); 111 1.1 riastrad 112 1.1 riastrad drm_modeset_acquire_init(ctx, 0); 113 1.1 riastrad 114 1.1 riastrad retry: 115 1.5 riastrad ret = drm_modeset_lock_all_ctx(dev, ctx); 116 1.5 riastrad if (ret < 0) { 117 1.5 riastrad if (ret == -EDEADLK) { 118 1.5 riastrad drm_modeset_backoff(ctx); 119 1.5 riastrad goto retry; 120 1.5 riastrad } 121 1.5 riastrad 122 1.5 riastrad drm_modeset_acquire_fini(ctx); 123 1.5 riastrad kfree(ctx); 124 1.5 riastrad return; 125 1.5 riastrad } 126 1.5 riastrad ww_acquire_done(&ctx->ww_ctx); 127 1.1 riastrad 128 1.1 riastrad WARN_ON(config->acquire_ctx); 129 1.1 riastrad 130 1.5 riastrad /* 131 1.5 riastrad * We hold the locks now, so it is safe to stash the acquisition 132 1.5 riastrad * context for drm_modeset_unlock_all(). 133 1.1 riastrad */ 134 1.1 riastrad config->acquire_ctx = ctx; 135 1.1 riastrad 136 1.1 riastrad drm_warn_on_modeset_not_all_locked(dev); 137 1.1 riastrad } 138 1.1 riastrad EXPORT_SYMBOL(drm_modeset_lock_all); 139 1.1 riastrad 140 1.1 riastrad /** 141 1.1 riastrad * drm_modeset_unlock_all - drop all modeset locks 142 1.5 riastrad * @dev: DRM device 143 1.5 riastrad * 144 1.5 riastrad * This function drops all modeset locks taken by a previous call to the 145 1.5 riastrad * drm_modeset_lock_all() function. 146 1.1 riastrad * 147 1.5 riastrad * This function is deprecated. It uses the lock acquisition context stored 148 1.5 riastrad * in &drm_device.mode_config. This facilitates conversion of existing 149 1.5 riastrad * code because it removes the need to manually deal with the acquisition 150 1.5 riastrad * context, but it is also brittle because the context is global and care must 151 1.5 riastrad * be taken not to nest calls. New code should pass the acquisition context 152 1.5 riastrad * directly to the drm_modeset_drop_locks() function. 153 1.1 riastrad */ 154 1.1 riastrad void drm_modeset_unlock_all(struct drm_device *dev) 155 1.1 riastrad { 156 1.1 riastrad struct drm_mode_config *config = &dev->mode_config; 157 1.1 riastrad struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx; 158 1.1 riastrad 159 1.1 riastrad if (WARN_ON(!ctx)) 160 1.1 riastrad return; 161 1.1 riastrad 162 1.1 riastrad config->acquire_ctx = NULL; 163 1.1 riastrad drm_modeset_drop_locks(ctx); 164 1.1 riastrad drm_modeset_acquire_fini(ctx); 165 1.1 riastrad 166 1.1 riastrad kfree(ctx); 167 1.1 riastrad 168 1.1 riastrad mutex_unlock(&dev->mode_config.mutex); 169 1.1 riastrad } 170 1.1 riastrad EXPORT_SYMBOL(drm_modeset_unlock_all); 171 1.1 riastrad 172 1.1 riastrad /** 173 1.1 riastrad * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked 174 1.1 riastrad * @dev: device 175 1.1 riastrad * 176 1.1 riastrad * Useful as a debug assert. 177 1.1 riastrad */ 178 1.1 riastrad void drm_warn_on_modeset_not_all_locked(struct drm_device *dev) 179 1.1 riastrad { 180 1.1 riastrad struct drm_crtc *crtc; 181 1.1 riastrad 182 1.1 riastrad /* Locking is currently fubar in the panic handler. */ 183 1.1 riastrad if (oops_in_progress) 184 1.1 riastrad return; 185 1.1 riastrad 186 1.1 riastrad drm_for_each_crtc(crtc, dev) 187 1.1 riastrad WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); 188 1.1 riastrad 189 1.1 riastrad WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); 190 1.1 riastrad WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); 191 1.1 riastrad } 192 1.1 riastrad EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked); 193 1.1 riastrad 194 1.1 riastrad /** 195 1.1 riastrad * drm_modeset_acquire_init - initialize acquire context 196 1.1 riastrad * @ctx: the acquire context 197 1.5 riastrad * @flags: 0 or %DRM_MODESET_ACQUIRE_INTERRUPTIBLE 198 1.5 riastrad * 199 1.5 riastrad * When passing %DRM_MODESET_ACQUIRE_INTERRUPTIBLE to @flags, 200 1.5 riastrad * all calls to drm_modeset_lock() will perform an interruptible 201 1.5 riastrad * wait. 202 1.1 riastrad */ 203 1.1 riastrad void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx, 204 1.1 riastrad uint32_t flags) 205 1.1 riastrad { 206 1.1 riastrad memset(ctx, 0, sizeof(*ctx)); 207 1.1 riastrad ww_acquire_init(&ctx->ww_ctx, &crtc_ww_class); 208 1.1 riastrad INIT_LIST_HEAD(&ctx->locked); 209 1.5 riastrad 210 1.5 riastrad if (flags & DRM_MODESET_ACQUIRE_INTERRUPTIBLE) 211 1.5 riastrad ctx->interruptible = true; 212 1.1 riastrad } 213 1.1 riastrad EXPORT_SYMBOL(drm_modeset_acquire_init); 214 1.1 riastrad 215 1.1 riastrad /** 216 1.1 riastrad * drm_modeset_acquire_fini - cleanup acquire context 217 1.1 riastrad * @ctx: the acquire context 218 1.1 riastrad */ 219 1.1 riastrad void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx) 220 1.1 riastrad { 221 1.1 riastrad ww_acquire_fini(&ctx->ww_ctx); 222 1.1 riastrad } 223 1.1 riastrad EXPORT_SYMBOL(drm_modeset_acquire_fini); 224 1.1 riastrad 225 1.1 riastrad /** 226 1.1 riastrad * drm_modeset_drop_locks - drop all locks 227 1.1 riastrad * @ctx: the acquire context 228 1.1 riastrad * 229 1.1 riastrad * Drop all locks currently held against this acquire context. 230 1.1 riastrad */ 231 1.1 riastrad void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx) 232 1.1 riastrad { 233 1.1 riastrad WARN_ON(ctx->contended); 234 1.1 riastrad while (!list_empty(&ctx->locked)) { 235 1.1 riastrad struct drm_modeset_lock *lock; 236 1.1 riastrad 237 1.1 riastrad lock = list_first_entry(&ctx->locked, 238 1.1 riastrad struct drm_modeset_lock, head); 239 1.1 riastrad 240 1.1 riastrad drm_modeset_unlock(lock); 241 1.1 riastrad } 242 1.1 riastrad } 243 1.1 riastrad EXPORT_SYMBOL(drm_modeset_drop_locks); 244 1.1 riastrad 245 1.1 riastrad static inline int modeset_lock(struct drm_modeset_lock *lock, 246 1.1 riastrad struct drm_modeset_acquire_ctx *ctx, 247 1.1 riastrad bool interruptible, bool slow) 248 1.1 riastrad { 249 1.1 riastrad int ret; 250 1.1 riastrad 251 1.1 riastrad WARN_ON(ctx->contended); 252 1.1 riastrad 253 1.1 riastrad if (ctx->trylock_only) { 254 1.1 riastrad lockdep_assert_held(&ctx->ww_ctx); 255 1.1 riastrad 256 1.1 riastrad if (!ww_mutex_trylock(&lock->mutex)) 257 1.1 riastrad return -EBUSY; 258 1.1 riastrad else 259 1.1 riastrad return 0; 260 1.1 riastrad } else if (interruptible && slow) { 261 1.1 riastrad ret = ww_mutex_lock_slow_interruptible(&lock->mutex, &ctx->ww_ctx); 262 1.1 riastrad } else if (interruptible) { 263 1.1 riastrad ret = ww_mutex_lock_interruptible(&lock->mutex, &ctx->ww_ctx); 264 1.1 riastrad } else if (slow) { 265 1.1 riastrad ww_mutex_lock_slow(&lock->mutex, &ctx->ww_ctx); 266 1.1 riastrad ret = 0; 267 1.1 riastrad } else { 268 1.1 riastrad ret = ww_mutex_lock(&lock->mutex, &ctx->ww_ctx); 269 1.1 riastrad } 270 1.1 riastrad if (!ret) { 271 1.1 riastrad WARN_ON(!list_empty(&lock->head)); 272 1.1 riastrad list_add(&lock->head, &ctx->locked); 273 1.1 riastrad } else if (ret == -EALREADY) { 274 1.1 riastrad /* we already hold the lock.. this is fine. For atomic 275 1.1 riastrad * we will need to be able to drm_modeset_lock() things 276 1.1 riastrad * without having to keep track of what is already locked 277 1.1 riastrad * or not. 278 1.1 riastrad */ 279 1.1 riastrad ret = 0; 280 1.1 riastrad } else if (ret == -EDEADLK) { 281 1.1 riastrad ctx->contended = lock; 282 1.1 riastrad } 283 1.1 riastrad 284 1.1 riastrad return ret; 285 1.1 riastrad } 286 1.1 riastrad 287 1.5 riastrad /** 288 1.5 riastrad * drm_modeset_backoff - deadlock avoidance backoff 289 1.5 riastrad * @ctx: the acquire context 290 1.5 riastrad * 291 1.5 riastrad * If deadlock is detected (ie. drm_modeset_lock() returns -EDEADLK), 292 1.5 riastrad * you must call this function to drop all currently held locks and 293 1.5 riastrad * block until the contended lock becomes available. 294 1.5 riastrad * 295 1.5 riastrad * This function returns 0 on success, or -ERESTARTSYS if this context 296 1.5 riastrad * is initialized with %DRM_MODESET_ACQUIRE_INTERRUPTIBLE and the 297 1.5 riastrad * wait has been interrupted. 298 1.5 riastrad */ 299 1.5 riastrad int drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx) 300 1.1 riastrad { 301 1.1 riastrad struct drm_modeset_lock *contended = ctx->contended; 302 1.1 riastrad 303 1.1 riastrad ctx->contended = NULL; 304 1.1 riastrad 305 1.1 riastrad if (WARN_ON(!contended)) 306 1.1 riastrad return 0; 307 1.1 riastrad 308 1.1 riastrad drm_modeset_drop_locks(ctx); 309 1.1 riastrad 310 1.5 riastrad return modeset_lock(contended, ctx, ctx->interruptible, true); 311 1.1 riastrad } 312 1.1 riastrad EXPORT_SYMBOL(drm_modeset_backoff); 313 1.1 riastrad 314 1.1 riastrad /** 315 1.5 riastrad * drm_modeset_lock_init - initialize lock 316 1.5 riastrad * @lock: lock to init 317 1.1 riastrad */ 318 1.5 riastrad void drm_modeset_lock_init(struct drm_modeset_lock *lock) 319 1.1 riastrad { 320 1.5 riastrad ww_mutex_init(&lock->mutex, &crtc_ww_class); 321 1.5 riastrad INIT_LIST_HEAD(&lock->head); 322 1.1 riastrad } 323 1.5 riastrad EXPORT_SYMBOL(drm_modeset_lock_init); 324 1.1 riastrad 325 1.1 riastrad /** 326 1.1 riastrad * drm_modeset_lock - take modeset lock 327 1.1 riastrad * @lock: lock to take 328 1.1 riastrad * @ctx: acquire ctx 329 1.1 riastrad * 330 1.5 riastrad * If @ctx is not NULL, then its ww acquire context is used and the 331 1.1 riastrad * lock will be tracked by the context and can be released by calling 332 1.1 riastrad * drm_modeset_drop_locks(). If -EDEADLK is returned, this means a 333 1.1 riastrad * deadlock scenario has been detected and it is an error to attempt 334 1.1 riastrad * to take any more locks without first calling drm_modeset_backoff(). 335 1.5 riastrad * 336 1.5 riastrad * If the @ctx is not NULL and initialized with 337 1.5 riastrad * %DRM_MODESET_ACQUIRE_INTERRUPTIBLE, this function will fail with 338 1.5 riastrad * -ERESTARTSYS when interrupted. 339 1.5 riastrad * 340 1.5 riastrad * If @ctx is NULL then the function call behaves like a normal, 341 1.5 riastrad * uninterruptible non-nesting mutex_lock() call. 342 1.1 riastrad */ 343 1.1 riastrad int drm_modeset_lock(struct drm_modeset_lock *lock, 344 1.1 riastrad struct drm_modeset_acquire_ctx *ctx) 345 1.1 riastrad { 346 1.1 riastrad if (ctx) 347 1.5 riastrad return modeset_lock(lock, ctx, ctx->interruptible, false); 348 1.1 riastrad 349 1.1 riastrad ww_mutex_lock(&lock->mutex, NULL); 350 1.1 riastrad return 0; 351 1.1 riastrad } 352 1.1 riastrad EXPORT_SYMBOL(drm_modeset_lock); 353 1.1 riastrad 354 1.1 riastrad /** 355 1.5 riastrad * drm_modeset_lock_single_interruptible - take a single modeset lock 356 1.1 riastrad * @lock: lock to take 357 1.1 riastrad * 358 1.5 riastrad * This function behaves as drm_modeset_lock() with a NULL context, 359 1.5 riastrad * but performs interruptible waits. 360 1.5 riastrad * 361 1.5 riastrad * This function returns 0 on success, or -ERESTARTSYS when interrupted. 362 1.1 riastrad */ 363 1.5 riastrad int drm_modeset_lock_single_interruptible(struct drm_modeset_lock *lock) 364 1.1 riastrad { 365 1.1 riastrad return ww_mutex_lock_interruptible(&lock->mutex, NULL); 366 1.1 riastrad } 367 1.5 riastrad EXPORT_SYMBOL(drm_modeset_lock_single_interruptible); 368 1.1 riastrad 369 1.1 riastrad /** 370 1.1 riastrad * drm_modeset_unlock - drop modeset lock 371 1.1 riastrad * @lock: lock to release 372 1.1 riastrad */ 373 1.1 riastrad void drm_modeset_unlock(struct drm_modeset_lock *lock) 374 1.1 riastrad { 375 1.1 riastrad list_del_init(&lock->head); 376 1.1 riastrad ww_mutex_unlock(&lock->mutex); 377 1.1 riastrad } 378 1.1 riastrad EXPORT_SYMBOL(drm_modeset_unlock); 379 1.1 riastrad 380 1.5 riastrad /** 381 1.5 riastrad * drm_modeset_lock_all_ctx - take all modeset locks 382 1.5 riastrad * @dev: DRM device 383 1.5 riastrad * @ctx: lock acquisition context 384 1.5 riastrad * 385 1.5 riastrad * This function takes all modeset locks, suitable where a more fine-grained 386 1.5 riastrad * scheme isn't (yet) implemented. 387 1.5 riastrad * 388 1.5 riastrad * Unlike drm_modeset_lock_all(), it doesn't take the &drm_mode_config.mutex 389 1.5 riastrad * since that lock isn't required for modeset state changes. Callers which 390 1.5 riastrad * need to grab that lock too need to do so outside of the acquire context 391 1.5 riastrad * @ctx. 392 1.5 riastrad * 393 1.5 riastrad * Locks acquired with this function should be released by calling the 394 1.5 riastrad * drm_modeset_drop_locks() function on @ctx. 395 1.5 riastrad * 396 1.5 riastrad * See also: DRM_MODESET_LOCK_ALL_BEGIN() and DRM_MODESET_LOCK_ALL_END() 397 1.5 riastrad * 398 1.5 riastrad * Returns: 0 on success or a negative error-code on failure. 399 1.5 riastrad */ 400 1.5 riastrad int drm_modeset_lock_all_ctx(struct drm_device *dev, 401 1.5 riastrad struct drm_modeset_acquire_ctx *ctx) 402 1.1 riastrad { 403 1.5 riastrad struct drm_private_obj *privobj; 404 1.1 riastrad struct drm_crtc *crtc; 405 1.1 riastrad struct drm_plane *plane; 406 1.5 riastrad int ret; 407 1.5 riastrad 408 1.5 riastrad ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx); 409 1.5 riastrad if (ret) 410 1.5 riastrad return ret; 411 1.1 riastrad 412 1.1 riastrad drm_for_each_crtc(crtc, dev) { 413 1.1 riastrad ret = drm_modeset_lock(&crtc->mutex, ctx); 414 1.1 riastrad if (ret) 415 1.1 riastrad return ret; 416 1.1 riastrad } 417 1.1 riastrad 418 1.1 riastrad drm_for_each_plane(plane, dev) { 419 1.1 riastrad ret = drm_modeset_lock(&plane->mutex, ctx); 420 1.1 riastrad if (ret) 421 1.1 riastrad return ret; 422 1.1 riastrad } 423 1.1 riastrad 424 1.5 riastrad drm_for_each_privobj(privobj, dev) { 425 1.5 riastrad ret = drm_modeset_lock(&privobj->lock, ctx); 426 1.5 riastrad if (ret) 427 1.5 riastrad return ret; 428 1.5 riastrad } 429 1.5 riastrad 430 1.1 riastrad return 0; 431 1.1 riastrad } 432 1.5 riastrad EXPORT_SYMBOL(drm_modeset_lock_all_ctx); 433