aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2014-11-11 04:12:00 -0500
committerDave Airlie <airlied@redhat.com>2014-11-12 02:56:12 -0500
commit4d02e2de0e80a786452e70d7f3a20a50641e6620 (patch)
tree4f3614925a25bab36ec2bb08c93ec836711ca928
parent5ee3229c87d396cab3c2dfc335b90320cc4a2f42 (diff)
drm: Per-plane locking
Turned out to be much simpler on top of my latest atomic stuff than what I've feared. Some details: - Drop the modeset_lock_all snakeoil in drm_plane_init. Same justification as for the equivalent change in drm_crtc_init done in commit d0fa1af40e784aaf7ebb7ba8a17b229bb3fa4c21 Author: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Mon Sep 8 09:02:49 2014 +0200 drm: Drop modeset locking from crtc init function Without these the drm_modeset_lock_init would fall over the exact same way. - Since the atomic core code wraps the locking switching it to per-plane locks was a one-line change. - For the legacy ioctls add a plane argument to the locking helper so that we can grab the right plane lock (cursor or primary). Since the universal cursor plane might not be there, or someone really crazy might forgoe the primary plane even accept NULL. - Add some locking WARN_ON to the atomic helpers for good paranoid measure and to check that it all works out. Tested on my exynos atomic hackfest with full lockdep checks and ww backoff injection. v2: I've forgotten about the load-detect code in i915. v3: Thierry reported that in latest 3.18-rc vmwgfx doesn't compile any more due to commit 21e88620aa21b48d4f62d29275e3e2944a5ea2b5 Author: Rob Clark <robdclark@gmail.com> Date: Thu Oct 30 13:39:04 2014 -0400 drm/vmwgfx: fix lock breakage Rebased and fix this up. Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Reviewed-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_atomic.c2
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c4
-rw-r--r--drivers/gpu/drm/drm_crtc.c9
-rw-r--r--drivers/gpu/drm/drm_modeset_lock.c43
-rw-r--r--drivers/gpu/drm/i915/intel_display.c6
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c4
-rw-r--r--include/drm/drm_crtc.h2
-rw-r--r--include/drm/drm_modeset_lock.h4
8 files changed, 55 insertions, 19 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index ed991ba66e21..ed22a719440f 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -244,7 +244,7 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
244 * grab all crtc locks. Once we have per-plane locks we must update this 244 * grab all crtc locks. Once we have per-plane locks we must update this
245 * to only take the plane mutex. 245 * to only take the plane mutex.
246 */ 246 */
247 ret = drm_modeset_lock_all_crtcs(state->dev, state->acquire_ctx); 247 ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx);
248 if (ret) 248 if (ret)
249 return ERR_PTR(ret); 249 return ERR_PTR(ret);
250 250
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index fad2b932cf72..c0a07cba3aaa 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1006,6 +1006,8 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
1006 if (!crtc) 1006 if (!crtc)
1007 continue; 1007 continue;
1008 1008
1009 WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
1010
1009 funcs = crtc->helper_private; 1011 funcs = crtc->helper_private;
1010 1012
1011 if (!funcs || !funcs->atomic_begin) 1013 if (!funcs || !funcs->atomic_begin)
@@ -1021,6 +1023,8 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
1021 if (!plane) 1023 if (!plane)
1022 continue; 1024 continue;
1023 1025
1026 WARN_ON(!drm_modeset_is_locked(&plane->mutex));
1027
1024 funcs = plane->helper_private; 1028 funcs = plane->helper_private;
1025 1029
1026 if (!funcs || !funcs->atomic_update) 1030 if (!funcs || !funcs->atomic_update)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index e6c169152bf1..3652ed8dda80 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1152,12 +1152,12 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
1152{ 1152{
1153 int ret; 1153 int ret;
1154 1154
1155 drm_modeset_lock_all(dev);
1156
1157 ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); 1155 ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
1158 if (ret) 1156 if (ret)
1159 goto out; 1157 goto out;
1160 1158
1159 drm_modeset_lock_init(&plane->mutex);
1160
1161 plane->base.properties = &plane->properties; 1161 plane->base.properties = &plane->properties;
1162 plane->dev = dev; 1162 plane->dev = dev;
1163 plane->funcs = funcs; 1163 plane->funcs = funcs;
@@ -1185,7 +1185,6 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
1185 plane->type); 1185 plane->type);
1186 1186
1187 out: 1187 out:
1188 drm_modeset_unlock_all(dev);
1189 1188
1190 return ret; 1189 return ret;
1191} 1190}
@@ -2809,7 +2808,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
2809 * If this crtc has a universal cursor plane, call that plane's update 2808 * If this crtc has a universal cursor plane, call that plane's update
2810 * handler rather than using legacy cursor handlers. 2809 * handler rather than using legacy cursor handlers.
2811 */ 2810 */
2812 drm_modeset_lock_crtc(crtc); 2811 drm_modeset_lock_crtc(crtc, crtc->cursor);
2813 if (crtc->cursor) { 2812 if (crtc->cursor) {
2814 ret = drm_mode_cursor_universal(crtc, req, file_priv); 2813 ret = drm_mode_cursor_universal(crtc, req, file_priv);
2815 goto out; 2814 goto out;
@@ -4598,7 +4597,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4598 if (!crtc) 4597 if (!crtc)
4599 return -ENOENT; 4598 return -ENOENT;
4600 4599
4601 drm_modeset_lock_crtc(crtc); 4600 drm_modeset_lock_crtc(crtc, crtc->primary);
4602 if (crtc->primary->fb == NULL) { 4601 if (crtc->primary->fb == NULL) {
4603 /* The framebuffer is currently unbound, presumably 4602 /* The framebuffer is currently unbound, presumably
4604 * due to a hotplug event, that userspace has not 4603 * due to a hotplug event, that userspace has not
diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index 474e4d12a2d8..51cc47d827d8 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -157,14 +157,20 @@ void drm_modeset_unlock_all(struct drm_device *dev)
157EXPORT_SYMBOL(drm_modeset_unlock_all); 157EXPORT_SYMBOL(drm_modeset_unlock_all);
158 158
159/** 159/**
160 * drm_modeset_lock_crtc - lock crtc with hidden acquire ctx 160 * drm_modeset_lock_crtc - lock crtc with hidden acquire ctx for a plane update
161 * @crtc: drm crtc 161 * @crtc: DRM CRTC
162 * @plane: DRM plane to be updated on @crtc
163 *
164 * This function locks the given crtc and plane (which should be either the
165 * primary or cursor plane) using a hidden acquire context. This is necessary so
166 * that drivers internally using the atomic interfaces can grab further locks
167 * with the lock acquire context.
162 * 168 *
163 * This function locks the given crtc using a hidden acquire context. This is 169 * Note that @plane can be NULL, e.g. when the cursor support hasn't yet been
164 * necessary so that drivers internally using the atomic interfaces can grab 170 * converted to universal planes yet.
165 * further locks with the lock acquire context.
166 */ 171 */
167void drm_modeset_lock_crtc(struct drm_crtc *crtc) 172void drm_modeset_lock_crtc(struct drm_crtc *crtc,
173 struct drm_plane *plane)
168{ 174{
169 struct drm_modeset_acquire_ctx *ctx; 175 struct drm_modeset_acquire_ctx *ctx;
170 int ret; 176 int ret;
@@ -180,6 +186,18 @@ retry:
180 if (ret) 186 if (ret)
181 goto fail; 187 goto fail;
182 188
189 if (plane) {
190 ret = drm_modeset_lock(&plane->mutex, ctx);
191 if (ret)
192 goto fail;
193
194 if (plane->crtc) {
195 ret = drm_modeset_lock(&plane->crtc->mutex, ctx);
196 if (ret)
197 goto fail;
198 }
199 }
200
183 WARN_ON(crtc->acquire_ctx); 201 WARN_ON(crtc->acquire_ctx);
184 202
185 /* now we hold the locks, so now that it is safe, stash the 203 /* now we hold the locks, so now that it is safe, stash the
@@ -437,15 +455,14 @@ void drm_modeset_unlock(struct drm_modeset_lock *lock)
437} 455}
438EXPORT_SYMBOL(drm_modeset_unlock); 456EXPORT_SYMBOL(drm_modeset_unlock);
439 457
440/* Temporary.. until we have sufficiently fine grained locking, there 458/* In some legacy codepaths it's convenient to just grab all the crtc and plane
441 * are a couple scenarios where it is convenient to grab all crtc locks. 459 * related locks. */
442 * It is planned to remove this:
443 */
444int drm_modeset_lock_all_crtcs(struct drm_device *dev, 460int drm_modeset_lock_all_crtcs(struct drm_device *dev,
445 struct drm_modeset_acquire_ctx *ctx) 461 struct drm_modeset_acquire_ctx *ctx)
446{ 462{
447 struct drm_mode_config *config = &dev->mode_config; 463 struct drm_mode_config *config = &dev->mode_config;
448 struct drm_crtc *crtc; 464 struct drm_crtc *crtc;
465 struct drm_plane *plane;
449 int ret = 0; 466 int ret = 0;
450 467
451 list_for_each_entry(crtc, &config->crtc_list, head) { 468 list_for_each_entry(crtc, &config->crtc_list, head) {
@@ -454,6 +471,12 @@ int drm_modeset_lock_all_crtcs(struct drm_device *dev,
454 return ret; 471 return ret;
455 } 472 }
456 473
474 list_for_each_entry(plane, &config->plane_list, head) {
475 ret = drm_modeset_lock(&plane->mutex, ctx);
476 if (ret)
477 return ret;
478 }
479
457 return 0; 480 return 0;
458} 481}
459EXPORT_SYMBOL(drm_modeset_lock_all_crtcs); 482EXPORT_SYMBOL(drm_modeset_lock_all_crtcs);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 31bb1d7acf9b..5fae12cf1072 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8730,6 +8730,9 @@ retry:
8730 ret = drm_modeset_lock(&crtc->mutex, ctx); 8730 ret = drm_modeset_lock(&crtc->mutex, ctx);
8731 if (ret) 8731 if (ret)
8732 goto fail_unlock; 8732 goto fail_unlock;
8733 ret = drm_modeset_lock(&crtc->primary->mutex, ctx);
8734 if (ret)
8735 goto fail_unlock;
8733 8736
8734 old->dpms_mode = connector->dpms; 8737 old->dpms_mode = connector->dpms;
8735 old->load_detect_temp = false; 8738 old->load_detect_temp = false;
@@ -8767,6 +8770,9 @@ retry:
8767 ret = drm_modeset_lock(&crtc->mutex, ctx); 8770 ret = drm_modeset_lock(&crtc->mutex, ctx);
8768 if (ret) 8771 if (ret)
8769 goto fail_unlock; 8772 goto fail_unlock;
8773 ret = drm_modeset_lock(&crtc->primary->mutex, ctx);
8774 if (ret)
8775 goto fail_unlock;
8770 intel_encoder->new_crtc = to_intel_crtc(crtc); 8776 intel_encoder->new_crtc = to_intel_crtc(crtc);
8771 to_intel_connector(connector)->new_encoder = intel_encoder; 8777 to_intel_connector(connector)->new_encoder = intel_encoder;
8772 8778
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 941a7bc0b791..3725b521d931 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -252,7 +252,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
252 ret = 0; 252 ret = 0;
253out: 253out:
254 drm_modeset_unlock_all(dev_priv->dev); 254 drm_modeset_unlock_all(dev_priv->dev);
255 drm_modeset_lock_crtc(crtc); 255 drm_modeset_lock_crtc(crtc, crtc->cursor);
256 256
257 return ret; 257 return ret;
258} 258}
@@ -281,7 +281,7 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
281 du->cursor_y + du->hotspot_y); 281 du->cursor_y + du->hotspot_y);
282 282
283 drm_modeset_unlock_all(dev_priv->dev); 283 drm_modeset_unlock_all(dev_priv->dev);
284 drm_modeset_lock_crtc(crtc); 284 drm_modeset_lock_crtc(crtc, crtc->cursor);
285 285
286 return 0; 286 return 0;
287} 287}
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index bc1cc3ce05c4..cbb475654b1c 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -751,6 +751,8 @@ struct drm_plane {
751 struct drm_device *dev; 751 struct drm_device *dev;
752 struct list_head head; 752 struct list_head head;
753 753
754 struct drm_modeset_lock mutex;
755
754 struct drm_mode_object base; 756 struct drm_mode_object base;
755 757
756 uint32_t possible_crtcs; 758 uint32_t possible_crtcs;
diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h
index 28931a23d96c..70595ff565ba 100644
--- a/include/drm/drm_modeset_lock.h
+++ b/include/drm/drm_modeset_lock.h
@@ -127,11 +127,13 @@ void drm_modeset_unlock(struct drm_modeset_lock *lock);
127 127
128struct drm_device; 128struct drm_device;
129struct drm_crtc; 129struct drm_crtc;
130struct drm_plane;
130 131
131void drm_modeset_lock_all(struct drm_device *dev); 132void drm_modeset_lock_all(struct drm_device *dev);
132int __drm_modeset_lock_all(struct drm_device *dev, bool trylock); 133int __drm_modeset_lock_all(struct drm_device *dev, bool trylock);
133void drm_modeset_unlock_all(struct drm_device *dev); 134void drm_modeset_unlock_all(struct drm_device *dev);
134void drm_modeset_lock_crtc(struct drm_crtc *crtc); 135void drm_modeset_lock_crtc(struct drm_crtc *crtc,
136 struct drm_plane *plane);
135void drm_modeset_unlock_crtc(struct drm_crtc *crtc); 137void drm_modeset_unlock_crtc(struct drm_crtc *crtc);
136void drm_warn_on_modeset_not_all_locked(struct drm_device *dev); 138void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
137struct drm_modeset_acquire_ctx * 139struct drm_modeset_acquire_ctx *