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>
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index b459e8fb..4cf6905 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -231,6 +231,7 @@
  * struct drm_crtc_state - mutable CRTC state
  * @enable: whether the CRTC should be enabled, gates all other state
  * @mode_changed: for use by helpers and drivers when computing state updates
+ * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
  * @last_vblank_count: for helpers and drivers to capture the vblank of the
  * 	update to ensure framebuffer cleanup isn't done too early
  * @planes_changed: for use by helpers and drivers when computing state updates
@@ -247,6 +248,13 @@
 	bool planes_changed : 1;
 	bool mode_changed : 1;
 
+	/* attached planes bitmask:
+	 * WARNING: transitional helpers do not maintain plane_mask so
+	 * drivers not converted over to atomic helpers should not rely
+	 * on plane_mask being accurate!
+	 */
+	u32 plane_mask;
+
 	/* last_vblank_count: for vblank waits before cleanup */
 	u32 last_vblank_count;
 
@@ -438,7 +446,7 @@
  * @state: backpointer to global drm_atomic_state
  */
 struct drm_connector_state {
-	struct drm_crtc *crtc;
+	struct drm_crtc *crtc;  /* do not write directly, use drm_atomic_set_crtc_for_connector() */
 
 	struct drm_encoder *best_encoder;
 
@@ -673,8 +681,8 @@
  * @state: backpointer to global drm_atomic_state
  */
 struct drm_plane_state {
-	struct drm_crtc *crtc;
-	struct drm_framebuffer *fb;
+	struct drm_crtc *crtc;   /* do not write directly, use drm_atomic_set_crtc_for_plane() */
+	struct drm_framebuffer *fb;  /* do not write directly, use drm_atomic_set_fb_for_plane() */
 	struct fence *fence;
 
 	/* Signed dest location allows it to be partially off screen */