diff options
author | Thierry Reding <treding@nvidia.com> | 2015-12-02 11:50:03 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-12-02 17:10:59 -0500 |
commit | 06eaae46381737a6236ad6fe81e5358fad3bbbe5 (patch) | |
tree | c5c69b47219e50729a136f0466dec7966f2c8756 | |
parent | 737292a3c0f251a93dcce4bedf7e4accb35335bc (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.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_modeset_lock.c | 89 | ||||
-rw-r--r-- | include/drm/drm_modeset_lock.h | 4 |
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) | |||
1188 | retry: | 1188 | retry: |
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 | */ |
66 | void drm_modeset_lock_all(struct drm_device *dev) | 73 | void 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 | ||
80 | retry: | 87 | retry: |
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 | |||
99 | fail: | ||
100 | if (ret == -EDEADLK) { | ||
101 | drm_modeset_backoff(ctx); | ||
102 | goto retry; | ||
103 | } | ||
104 | |||
105 | kfree(ctx); | ||
106 | } | 109 | } |
107 | EXPORT_SYMBOL(drm_modeset_lock_all); | 110 | EXPORT_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 | */ |
115 | void drm_modeset_unlock_all(struct drm_device *dev) | 126 | void 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 | } |
432 | EXPORT_SYMBOL(drm_modeset_unlock); | 443 | EXPORT_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 |
436 | int 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 | */ | ||
463 | int 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 | } |
457 | EXPORT_SYMBOL(drm_modeset_lock_all_crtcs); | 488 | EXPORT_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); | |||
138 | struct drm_modeset_acquire_ctx * | 138 | struct drm_modeset_acquire_ctx * |
139 | drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc); | 139 | drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc); |
140 | 140 | ||
141 | int drm_modeset_lock_all_crtcs(struct drm_device *dev, | 141 | int 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_ */ |