aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2014-11-21 15:28:31 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-11-27 09:38:15 -0500
commit6ddd388ab222b66b596342becc76d5031c0e2fc8 (patch)
treea13411bc126896dc7a4a61a442657beb02ef59eb
parent3009c0377f25c29852b218a6933a969d02cbdc5d (diff)
drm/atomic: track bitmask of planes attached to crtc
Chasing plane->state->crtc of planes that are *not* part of the same atomic update is racy, making it incredibly awkward (or impossible) to do something simple like iterate over all planes and figure out which ones are attached to a crtc. Solve this by adding a bitmask of currently attached planes in the crtc-state. Note that the transitional helpers do not maintain the plane_mask. But they only support the legacy ioctls, which have sufficient brute-force locking around plane updates that they can continue to loop over all planes to see what is attached to a crtc the old way. Signed-off-by: Rob Clark <robdclark@gmail.com> [danvet: - Drop comments about locking in set_crtc_for_plane since they're a bit misleading - we already should hold lock for the current crtc. - Also WARN_ON if get_state on the old crtc fails since that should have been done already. - Squash in fixup to check get_plane_state return value, reported by Dan Carpenter and acked by Rob Clark.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/drm_atomic.c26
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c8
-rw-r--r--include/drm/drm_atomic.h4
-rw-r--r--include/drm/drm_crtc.h14
4 files changed, 38 insertions, 14 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index ba49b5ca822f..ff5f034cc405 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -344,7 +344,8 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state);
344 344
345/** 345/**
346 * drm_atomic_set_crtc_for_plane - set crtc for plane 346 * drm_atomic_set_crtc_for_plane - set crtc for plane
347 * @plane_state: atomic state object for the plane 347 * @state: the incoming atomic state
348 * @plane: the plane whose incoming state to update
348 * @crtc: crtc to use for the plane 349 * @crtc: crtc to use for the plane
349 * 350 *
350 * Changing the assigned crtc for a plane requires us to grab the lock and state 351 * Changing the assigned crtc for a plane requires us to grab the lock and state
@@ -357,20 +358,35 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state);
357 * sequence must be restarted. All other errors are fatal. 358 * sequence must be restarted. All other errors are fatal.
358 */ 359 */
359int 360int
360drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, 361drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state,
361 struct drm_crtc *crtc) 362 struct drm_plane *plane, struct drm_crtc *crtc)
362{ 363{
364 struct drm_plane_state *plane_state =
365 drm_atomic_get_plane_state(state, plane);
363 struct drm_crtc_state *crtc_state; 366 struct drm_crtc_state *crtc_state;
364 367
368 if (WARN_ON(IS_ERR(plane_state)))
369 return PTR_ERR(plane_state);
370
371 if (plane_state->crtc) {
372 crtc_state = drm_atomic_get_crtc_state(plane_state->state,
373 plane_state->crtc);
374 if (WARN_ON(IS_ERR(crtc_state)))
375 return PTR_ERR(crtc_state);
376
377 crtc_state->plane_mask &= ~(1 << drm_plane_index(plane));
378 }
379
380 plane_state->crtc = crtc;
381
365 if (crtc) { 382 if (crtc) {
366 crtc_state = drm_atomic_get_crtc_state(plane_state->state, 383 crtc_state = drm_atomic_get_crtc_state(plane_state->state,
367 crtc); 384 crtc);
368 if (IS_ERR(crtc_state)) 385 if (IS_ERR(crtc_state))
369 return PTR_ERR(crtc_state); 386 return PTR_ERR(crtc_state);
387 crtc_state->plane_mask |= (1 << drm_plane_index(plane));
370 } 388 }
371 389
372 plane_state->crtc = crtc;
373
374 if (crtc) 390 if (crtc)
375 DRM_DEBUG_KMS("Link plane state %p to [CRTC:%d]\n", 391 DRM_DEBUG_KMS("Link plane state %p to [CRTC:%d]\n",
376 plane_state, crtc->base.id); 392 plane_state, crtc->base.id);
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 2fa0840694d0..2ee509c92034 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1222,7 +1222,7 @@ retry:
1222 goto fail; 1222 goto fail;
1223 } 1223 }
1224 1224
1225 ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); 1225 ret = drm_atomic_set_crtc_for_plane(state, plane, crtc);
1226 if (ret != 0) 1226 if (ret != 0)
1227 goto fail; 1227 goto fail;
1228 drm_atomic_set_fb_for_plane(plane_state, fb); 1228 drm_atomic_set_fb_for_plane(plane_state, fb);
@@ -1301,7 +1301,7 @@ retry:
1301 goto fail; 1301 goto fail;
1302 } 1302 }
1303 1303
1304 ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); 1304 ret = drm_atomic_set_crtc_for_plane(state, plane, NULL);
1305 if (ret != 0) 1305 if (ret != 0)
1306 goto fail; 1306 goto fail;
1307 drm_atomic_set_fb_for_plane(plane_state, NULL); 1307 drm_atomic_set_fb_for_plane(plane_state, NULL);
@@ -1472,7 +1472,7 @@ retry:
1472 goto fail; 1472 goto fail;
1473 } 1473 }
1474 1474
1475 ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); 1475 ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, crtc);
1476 if (ret != 0) 1476 if (ret != 0)
1477 goto fail; 1477 goto fail;
1478 drm_atomic_set_fb_for_plane(primary_state, set->fb); 1478 drm_atomic_set_fb_for_plane(primary_state, set->fb);
@@ -1744,7 +1744,7 @@ retry:
1744 goto fail; 1744 goto fail;
1745 } 1745 }
1746 1746
1747 ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); 1747 ret = drm_atomic_set_crtc_for_plane(state, plane, crtc);
1748 if (ret != 0) 1748 if (ret != 0)
1749 goto fail; 1749 goto fail;
1750 drm_atomic_set_fb_for_plane(plane_state, fb); 1750 drm_atomic_set_fb_for_plane(plane_state, fb);
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index e224ccfa11ca..ad2229574dd9 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -46,8 +46,8 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,
46 struct drm_connector *connector); 46 struct drm_connector *connector);
47 47
48int __must_check 48int __must_check
49drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, 49drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state,
50 struct drm_crtc *crtc); 50 struct drm_plane *plane, struct drm_crtc *crtc);
51void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, 51void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
52 struct drm_framebuffer *fb); 52 struct drm_framebuffer *fb);
53int __must_check 53int __must_check
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index b459e8fbbc25..4cf6905b57f5 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -231,6 +231,7 @@ struct drm_atomic_state;
231 * struct drm_crtc_state - mutable CRTC state 231 * struct drm_crtc_state - mutable CRTC state
232 * @enable: whether the CRTC should be enabled, gates all other state 232 * @enable: whether the CRTC should be enabled, gates all other state
233 * @mode_changed: for use by helpers and drivers when computing state updates 233 * @mode_changed: for use by helpers and drivers when computing state updates
234 * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
234 * @last_vblank_count: for helpers and drivers to capture the vblank of the 235 * @last_vblank_count: for helpers and drivers to capture the vblank of the
235 * update to ensure framebuffer cleanup isn't done too early 236 * update to ensure framebuffer cleanup isn't done too early
236 * @planes_changed: for use by helpers and drivers when computing state updates 237 * @planes_changed: for use by helpers and drivers when computing state updates
@@ -247,6 +248,13 @@ struct drm_crtc_state {
247 bool planes_changed : 1; 248 bool planes_changed : 1;
248 bool mode_changed : 1; 249 bool mode_changed : 1;
249 250
251 /* attached planes bitmask:
252 * WARNING: transitional helpers do not maintain plane_mask so
253 * drivers not converted over to atomic helpers should not rely
254 * on plane_mask being accurate!
255 */
256 u32 plane_mask;
257
250 /* last_vblank_count: for vblank waits before cleanup */ 258 /* last_vblank_count: for vblank waits before cleanup */
251 u32 last_vblank_count; 259 u32 last_vblank_count;
252 260
@@ -438,7 +446,7 @@ struct drm_crtc {
438 * @state: backpointer to global drm_atomic_state 446 * @state: backpointer to global drm_atomic_state
439 */ 447 */
440struct drm_connector_state { 448struct drm_connector_state {
441 struct drm_crtc *crtc; 449 struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_connector() */
442 450
443 struct drm_encoder *best_encoder; 451 struct drm_encoder *best_encoder;
444 452
@@ -673,8 +681,8 @@ struct drm_connector {
673 * @state: backpointer to global drm_atomic_state 681 * @state: backpointer to global drm_atomic_state
674 */ 682 */
675struct drm_plane_state { 683struct drm_plane_state {
676 struct drm_crtc *crtc; 684 struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */
677 struct drm_framebuffer *fb; 685 struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */
678 struct fence *fence; 686 struct fence *fence;
679 687
680 /* Signed dest location allows it to be partially off screen */ 688 /* Signed dest location allows it to be partially off screen */