aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2015-12-02 11:50:03 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-12-02 17:10:59 -0500
commit06eaae46381737a6236ad6fe81e5358fad3bbbe5 (patch)
treec5c69b47219e50729a136f0466dec7966f2c8756
parent737292a3c0f251a93dcce4bedf7e4accb35335bc (diff)
drm: Implement drm_modeset_lock_all_ctx()
This function is like drm_modeset_lock_all(), but it takes the lock acquisition context as a parameter rather than storing it in the DRM device's mode_config structure. Implement drm_modeset_{,un}lock_all() in terms of the new function for better code reuse, and add a note to the kerneldoc that new code should use the new functions. v2: improve kerneldoc v4: rename drm_modeset_lock_all_crtcs() to drm_modeset_lock_all_ctx() and take mode_config's .connection_mutex instead of .mutex lock to avoid lock inversion (Daniel Vetter), use drm_modeset_drop_locks() which is now the equivalent of drm_modeset_unlock_all_ctx() v5: do not take the dev->mode_config.connection_mutex in drm_atomic_legacy_backoff() since drm_modeset_lock_all_ctx() already keeps it, enhance kerneldoc for drm_modeset_lock_all_ctx() (Daniel Vetter) Signed-off-by: Thierry Reding <treding@nvidia.com> Link: http://patchwork.freedesktop.org/patch/msgid/1449075005-13937-1-git-send-email-thierry.reding@gmail.com Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/drm_atomic.c7
-rw-r--r--drivers/gpu/drm/drm_modeset_lock.c89
-rw-r--r--include/drm/drm_modeset_lock.h4
3 files changed, 63 insertions, 37 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 55b4debad79b..ef5f7663a718 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1188,12 +1188,7 @@ void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
1188retry: 1188retry:
1189 drm_modeset_backoff(state->acquire_ctx); 1189 drm_modeset_backoff(state->acquire_ctx);
1190 1190
1191 ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex, 1191 ret = drm_modeset_lock_all_ctx(state->dev, state->acquire_ctx);
1192 state->acquire_ctx);
1193 if (ret)
1194 goto retry;
1195 ret = drm_modeset_lock_all_crtcs(state->dev,
1196 state->acquire_ctx);
1197 if (ret) 1192 if (ret)
1198 goto retry; 1193 goto retry;
1199} 1194}
diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index 6675b1428410..c2f5971146ba 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -57,11 +57,18 @@
57 57
58/** 58/**
59 * drm_modeset_lock_all - take all modeset locks 59 * drm_modeset_lock_all - take all modeset locks
60 * @dev: drm device 60 * @dev: DRM device
61 * 61 *
62 * This function takes all modeset locks, suitable where a more fine-grained 62 * This function takes all modeset locks, suitable where a more fine-grained
63 * scheme isn't (yet) implemented. Locks must be dropped with 63 * scheme isn't (yet) implemented. Locks must be dropped by calling the
64 * drm_modeset_unlock_all. 64 * drm_modeset_unlock_all() function.
65 *
66 * This function is deprecated. It allocates a lock acquisition context and
67 * stores it in the DRM device's ->mode_config. This facilitate conversion of
68 * existing code because it removes the need to manually deal with the
69 * acquisition context, but it is also brittle because the context is global
70 * and care must be taken not to nest calls. New code should use the
71 * drm_modeset_lock_all_ctx() function and pass in the context explicitly.
65 */ 72 */
66void drm_modeset_lock_all(struct drm_device *dev) 73void drm_modeset_lock_all(struct drm_device *dev)
67{ 74{
@@ -78,39 +85,43 @@ void drm_modeset_lock_all(struct drm_device *dev)
78 drm_modeset_acquire_init(ctx, 0); 85 drm_modeset_acquire_init(ctx, 0);
79 86
80retry: 87retry:
81 ret = drm_modeset_lock(&config->connection_mutex, ctx); 88 ret = drm_modeset_lock_all_ctx(dev, ctx);
82 if (ret) 89 if (ret < 0) {
83 goto fail; 90 if (ret == -EDEADLK) {
84 ret = drm_modeset_lock_all_crtcs(dev, ctx); 91 drm_modeset_backoff(ctx);
85 if (ret) 92 goto retry;
86 goto fail; 93 }
94
95 drm_modeset_acquire_fini(ctx);
96 kfree(ctx);
97 return;
98 }
87 99
88 WARN_ON(config->acquire_ctx); 100 WARN_ON(config->acquire_ctx);
89 101
90 /* now we hold the locks, so now that it is safe, stash the 102 /*
91 * ctx for drm_modeset_unlock_all(): 103 * We hold the locks now, so it is safe to stash the acquisition
104 * context for drm_modeset_unlock_all().
92 */ 105 */
93 config->acquire_ctx = ctx; 106 config->acquire_ctx = ctx;
94 107
95 drm_warn_on_modeset_not_all_locked(dev); 108 drm_warn_on_modeset_not_all_locked(dev);
96
97 return;
98
99fail:
100 if (ret == -EDEADLK) {
101 drm_modeset_backoff(ctx);
102 goto retry;
103 }
104
105 kfree(ctx);
106} 109}
107EXPORT_SYMBOL(drm_modeset_lock_all); 110EXPORT_SYMBOL(drm_modeset_lock_all);
108 111
109/** 112/**
110 * drm_modeset_unlock_all - drop all modeset locks 113 * drm_modeset_unlock_all - drop all modeset locks
111 * @dev: device 114 * @dev: DRM device
112 * 115 *
113 * This function drop all modeset locks taken by drm_modeset_lock_all. 116 * This function drops all modeset locks taken by a previous call to the
117 * drm_modeset_lock_all() function.
118 *
119 * This function is deprecated. It uses the lock acquisition context stored
120 * in the DRM device's ->mode_config. This facilitates conversion of existing
121 * code because it removes the need to manually deal with the acquisition
122 * context, but it is also brittle because the context is global and care must
123 * be taken not to nest calls. New code should pass the acquisition context
124 * directly to the drm_modeset_drop_locks() function.
114 */ 125 */
115void drm_modeset_unlock_all(struct drm_device *dev) 126void drm_modeset_unlock_all(struct drm_device *dev)
116{ 127{
@@ -431,14 +442,34 @@ void drm_modeset_unlock(struct drm_modeset_lock *lock)
431} 442}
432EXPORT_SYMBOL(drm_modeset_unlock); 443EXPORT_SYMBOL(drm_modeset_unlock);
433 444
434/* In some legacy codepaths it's convenient to just grab all the crtc and plane 445/**
435 * related locks. */ 446 * drm_modeset_lock_all_ctx - take all modeset locks
436int drm_modeset_lock_all_crtcs(struct drm_device *dev, 447 * @dev: DRM device
437 struct drm_modeset_acquire_ctx *ctx) 448 * @ctx: lock acquisition context
449 *
450 * This function takes all modeset locks, suitable where a more fine-grained
451 * scheme isn't (yet) implemented.
452 *
453 * Unlike drm_modeset_lock_all(), it doesn't take the dev->mode_config.mutex
454 * since that lock isn't required for modeset state changes. Callers which
455 * need to grab that lock too need to do so outside of the acquire context
456 * @ctx.
457 *
458 * Locks acquired with this function should be released by calling the
459 * drm_modeset_drop_locks() function on @ctx.
460 *
461 * Returns: 0 on success or a negative error-code on failure.
462 */
463int drm_modeset_lock_all_ctx(struct drm_device *dev,
464 struct drm_modeset_acquire_ctx *ctx)
438{ 465{
439 struct drm_crtc *crtc; 466 struct drm_crtc *crtc;
440 struct drm_plane *plane; 467 struct drm_plane *plane;
441 int ret = 0; 468 int ret;
469
470 ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
471 if (ret)
472 return ret;
442 473
443 drm_for_each_crtc(crtc, dev) { 474 drm_for_each_crtc(crtc, dev) {
444 ret = drm_modeset_lock(&crtc->mutex, ctx); 475 ret = drm_modeset_lock(&crtc->mutex, ctx);
@@ -454,4 +485,4 @@ int drm_modeset_lock_all_crtcs(struct drm_device *dev,
454 485
455 return 0; 486 return 0;
456} 487}
457EXPORT_SYMBOL(drm_modeset_lock_all_crtcs); 488EXPORT_SYMBOL(drm_modeset_lock_all_ctx);
diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h
index 94938d89347c..c5576fbcb909 100644
--- a/include/drm/drm_modeset_lock.h
+++ b/include/drm/drm_modeset_lock.h
@@ -138,7 +138,7 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
138struct drm_modeset_acquire_ctx * 138struct drm_modeset_acquire_ctx *
139drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc); 139drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc);
140 140
141int drm_modeset_lock_all_crtcs(struct drm_device *dev, 141int drm_modeset_lock_all_ctx(struct drm_device *dev,
142 struct drm_modeset_acquire_ctx *ctx); 142 struct drm_modeset_acquire_ctx *ctx);
143 143
144#endif /* DRM_MODESET_LOCK_H_ */ 144#endif /* DRM_MODESET_LOCK_H_ */