atomic plane iterators
cover atomic plane iterators
Resend the series.. I think danvet has first one queued up on topic/core-stuff, second one updated from bikeshedding, adding the third which converts over msm to use the new iterator macros (now that mdp5 atomic stuff is on drm-next)
Rob Clark (3):
drm/atomic: track bitmask of planes attached to crtc drm/atomic: add plane iterator macros drm/msm: switch to atomic-helpers iterator macros
Documentation/DocBook/drm.tmpl | 1 + drivers/gpu/drm/drm_atomic.c | 23 ++++++++++++++++++----- drivers/gpu/drm/drm_atomic_helper.c | 8 ++++---- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 6 +++--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 9 +++++---- drivers/gpu/drm/msm/msm_kms.h | 23 ----------------------- include/drm/drm_atomic.h | 4 ++-- include/drm/drm_atomic_helper.h | 28 ++++++++++++++++++++++++++++ include/drm/drm_crtc.h | 14 +++++++++++--- 9 files changed, 72 insertions(+), 44 deletions(-)
Signature · 6 lines
1.9.3 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 1/3 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.
--- drivers/gpu/drm/drm_atomic.c | 23 ++++++++++++++++++----- drivers/gpu/drm/drm_atomic_helper.c | 8 ++++---- include/drm/drm_atomic.h | 4 ++-- include/drm/drm_crtc.h | 14 +++++++++++--- 4 files changed, 35 insertions(+), 14 deletions(-)
drivers/gpu/drm/drm_atomic.c +18 -5
@@ -350,7 +350,8 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state);/** * drm_atomic_set_crtc_for_plane - set crtc for plane -* @plane_state: atomic state object for the plane +* @state: the incoming atomic state +* @plane: the plane whose incoming state to update * @crtc: crtc to use for the plane * * Changing the assigned crtc for a plane requires us to grab the lock and state
@@ -363,20 +364,32 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state);* sequence must be restarted. All other errors are fatal. */ int -drm_atomic_set_crtc_for_plane (struct drm_plane_state *plane_state, -struct drm_crtc *crtc) +drm_atomic_set_crtc_for_plane (struct drm_atomic_state *state, +struct drm_plane *plane,struct drm_crtc *crtc) { +struct drm_plane_state *plane_state = +drm_atomic_get_plane_state (state, plane);struct drm_crtc_state *crtc_state; +if (plane_state->crtc) { + crtc_state =drm_atomic_get_crtc_state (plane_state->state, + plane_state->crtc); +if (WARN_ON (IS_ERR (crtc_state))) +return PTR_ERR (crtc_state); + + crtc_state->plane_mask &= ~(1 <<drm_plane_index (plane)); + } + + plane_state->crtc = crtc; +if (crtc) { crtc_state =drm_atomic_get_crtc_state (plane_state->state, crtc);if (IS_ERR (crtc_state))return PTR_ERR (crtc_state); + crtc_state->plane_mask |= (1 <<drm_plane_index (plane)); } - plane_state->crtc = crtc; -if (crtc)DRM_DEBUG_KMS ("Link plane state %p to [CRTC:%d]\n" , plane_state, crtc->base.id);
drivers/gpu/drm/drm_atomic_helper.c +4 -4
@@ -1187,7 +1187,7 @@ retry: goto fail; } - ret =drm_atomic_set_crtc_for_plane (plane_state, crtc); + ret =drm_atomic_set_crtc_for_plane (state, plane, crtc);if (ret !=0 ) goto fail;drm_atomic_set_fb_for_plane (plane_state, fb);
@@ -1255,7 +1255,7 @@ retry: goto fail; } - ret =drm_atomic_set_crtc_for_plane (plane_state,NULL ); + ret =drm_atomic_set_crtc_for_plane (state, plane,NULL );if (ret !=0 ) goto fail;drm_atomic_set_fb_for_plane (plane_state,NULL );
@@ -1426,7 +1426,7 @@ retry: goto fail; } - ret =drm_atomic_set_crtc_for_plane (primary_state, crtc); + ret =drm_atomic_set_crtc_for_plane (state, crtc->primary, crtc);if (ret !=0 ) goto fail;drm_atomic_set_fb_for_plane (primary_state, set->fb);
@@ -1698,7 +1698,7 @@ retry: goto fail; } - ret =drm_atomic_set_crtc_for_plane (plane_state, crtc); + ret =drm_atomic_set_crtc_for_plane (state, plane, crtc);if (ret !=0 ) goto fail;drm_atomic_set_fb_for_plane (plane_state, fb);
include/drm/drm_atomic.h +2 -2
@@ -44,8 +44,8 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, struct drm_connector *connector);int __must_check -drm_atomic_set_crtc_for_plane (struct drm_plane_state *plane_state, -struct drm_crtc *crtc); +drm_atomic_set_crtc_for_plane (struct drm_atomic_state *state, +struct drm_plane *plane,struct drm_crtc *crtc);void drm_atomic_set_fb_for_plane (struct drm_plane_state *plane_state,struct drm_framebuffer *fb);int __must_check
include/drm/drm_crtc.h +11 -3
@@ -231,6 +231,7 @@ struct drm_atomic_state;* 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 @@ struct drm_crtc_state { 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 @@ struct drm_crtc {* @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 @@ struct drm_connector {* @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 */
Signature · 6 lines
1.9.3 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 2/3 drm/atomic: add plane iterator macros
In reply to Rob ClarkAdd helper macros to iterate the current, or incoming set of planes attached to a crtc. These helpers are only available for drivers converted to use atomic-helpers.
--- Documentation/DocBook/drm.tmpl | 1 + include/drm/drm_atomic_helper.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+)
Documentation/DocBook/drm.tmpl +1 -0
@@ -2343,6 +2343,7 @@ void intel_crt_init(struct drm_device *dev) <title>Atomic State Reset and Initialization</title> !Pdrivers/gpu/drm/drm_atomic_helper.c atomic state reset and initialization </sect3> +!Iinclude/drm/drm_atomic_helper.h !Edrivers/gpu/drm/drm_atomic_helper.c </sect2> <sect2>
include/drm/drm_atomic_helper.h +28 -0
@@ -96,5 +96,33 @@ drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector);void drm_atomic_helper_connector_destroy_state (struct drm_connector *connector,struct drm_connector_state *state); +#define __drm_for_each_plane_mask (plane, dev, plane_mask) \ + list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \ + if ((plane_mask) & (1 << drm_plane_index(plane))) + +/** +* drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC +* @plane: the loop cursor +* @crtc: the crtc whose planes are iterated +* +* This iterates over the current state, useful (for example) when applying +* atomic state after it has been checked and swapped. To iterate over the +* planes which *will* be attached (for ->atomic_check()) see +* drm_crtc_for_each_pending_plane() +*/ +#define drm_atomic_crtc_for_each_plane (plane, crtc) \ + __drm_for_each_plane_mask(plane, (crtc)->dev, (crtc)->state->plane_mask) + +/** +* drm_crtc_atomic_state_for_each_plane - iterate over attached planes in new state +* @plane: the loop cursor +* @crtc_state: the incoming crtc-state +* +* Similar to drm_crtc_for_each_plane(), but iterates the planes that will be +* attached if the specified state is applied. Useful during (for example) +* ->atomic_check() operations, to validate the incoming state +*/ +#define drm_atomic_crtc_state_for_each_plane (plane, crtc_state) \ + __drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask)#endif /* DRM_ATOMIC_HELPER_H_ */
Signature · 6 lines
1.9.3 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 3/3 drm/msm: switch to atomic-helpers iterator macros
In reply to Rob Clark--- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 6 +++--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 9 +++++---- drivers/gpu/drm/msm/msm_kms.h | 23 ----------------------- 3 files changed, 8 insertions(+), 30 deletions(-)
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +3 -3
@@ -84,7 +84,7 @@ static void crtc_flush(struct drm_crtc *crtc)struct drm_plane *plane;uint32_t flush =0 ; -for_each_plane_on_crtc (crtc, plane) { +drm_atomic_crtc_for_each_plane (plane, crtc) {enum mdp4_pipe pipe_id =mdp4_plane_pipe (plane); flush |=pipe2flush (pipe_id); }
@@ -197,7 +197,7 @@ static void setup_mixer(struct mdp4_kms *mdp4_kms)struct mdp4_crtc *mdp4_crtc =to_mdp4_crtc (crtc);struct drm_plane *plane; -for_each_plane_on_crtc (crtc, plane) { +drm_atomic_crtc_for_each_plane (plane, crtc) {enum mdp4_pipe pipe_id =mdp4_plane_pipe (plane);int idx = idxs[pipe_id]; mixer_cfg = mixercfg(mixer_cfg, mdp4_crtc->mixer,
@@ -221,7 +221,7 @@ static void blend_setup(struct drm_crtc *crtc)mdp4_write (mdp4_kms,REG_MDP4_OVLP_TRANSP_HIGH0 (ovlp),0 );mdp4_write (mdp4_kms,REG_MDP4_OVLP_TRANSP_HIGH1 (ovlp),0 ); -for_each_plane_on_crtc (crtc, plane) { +drm_atomic_crtc_for_each_plane (plane, crtc) {enum mdp4_pipe pipe_id =mdp4_plane_pipe (plane);int idx = idxs[pipe_id];if (idx >0 ) {
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +5 -4
@@ -91,7 +91,7 @@ static void crtc_flush_all(struct drm_crtc *crtc)if (!mdp5_crtc->ctl)return ; -for_each_plane_on_crtc (crtc, plane) { +drm_atomic_crtc_for_each_plane (plane, crtc) { flush_mask |=mdp5_plane_get_flush (plane); } flush_mask |=mdp5_ctl_get_flush (mdp5_crtc->ctl);
@@ -124,8 +124,9 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file) }spin_unlock_irqrestore (&dev->event_lock, flags); -for_each_plane_on_crtc (crtc, plane) +drm_atomic_crtc_for_each_plane (plane, crtc) {mdp5_plane_complete_flip (plane); + } }static void mdp5_crtc_destroy (struct drm_crtc *crtc)
@@ -195,7 +196,7 @@ static void blend_setup(struct drm_crtc *crtc)if (!mdp5_crtc->ctl) goto out; -for_each_plane_on_crtc (crtc, plane) { +drm_atomic_crtc_for_each_plane (plane, crtc) {enum mdp_mixer_stage_id stage =to_mdp5_plane_state (plane->state)->stage;
@@ -317,7 +318,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,/* verify that there are not too many planes attached to crtc * and that we don't have conflicting mixer stages: */ -for_each_pending_plane_on_crtc (state->state, crtc, plane) { +drm_atomic_crtc_state_for_each_plane (plane, state) {struct drm_plane_state *pstate;if (cnt >=ARRAY_SIZE (pstates)) {
drivers/gpu/drm/msm/msm_kms.h +0 -23
@@ -65,27 +65,4 @@ static inline void msm_kms_init(struct msm_kms *kms,struct msm_kms *mdp4_kms_init (struct drm_device *dev);struct msm_kms *mdp5_kms_init (struct drm_device *dev); -/* TODO move these helper iterator macro somewhere common: */ -#define for_each_plane_on_crtc (_crtc, _plane) \ - list_for_each_entry((_plane), &(_crtc)->dev->mode_config.plane_list, head) \ - if ((_plane)->state->crtc == (_crtc)) - -static inline bool -__plane_will_be_attached_to_crtc (struct drm_atomic_state *state, -struct drm_plane *plane,struct drm_crtc *crtc) -{ -int idx =drm_plane_index (plane); - -/* if plane is modified in incoming state, use the new state: */ -if (state->plane_states[idx]) -return state->plane_states[idx]->crtc == crtc; - -/* otherwise, current state: */ -return plane->state->crtc == crtc; -} - -#define for_each_pending_plane_on_crtc (_state, _crtc, _plane) \ - list_for_each_entry((_plane), &(_crtc)->dev->mode_config.plane_list, head) \ - if (__plane_will_be_attached_to_crtc((_state), (_plane), (_crtc))) -#endif /* __MSM_KMS_H__ */
Signature · 6 lines
1.9.3 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/3] drm/msm: switch to atomic-helpers iterator macros
Quoted 1 line · Rob Clark
Signed-off-by Rob Clark <[email protected]>
Merged this and the iterator patch (I've had the planemask one already) into my fixup pile.
Thanks, Daniel
Quoted 114 lines
--- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 6 +++--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 9 +++++---- drivers/gpu/drm/msm/msm_kms.h | 23 ----------------------- 3 files changed, 8 insertions(+), 30 deletions(-)drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +3
-3@@ -84,7 +84,7 @@ static void crtc_flush(struct drm_crtc *crtc)struct drm_plane *plane;uint32_t flush =0 ; -for_each_plane_on_crtc (crtc, plane) { +drm_atomic_crtc_for_each_plane (plane, crtc) {enum mdp4_pipe pipe_id =mdp4_plane_pipe (plane); flush |=pipe2flush (pipe_id); }@@ -197,7 +197,7 @@ static void setup_mixer(struct mdp4_kms *mdp4_kms)struct mdp4_crtc *mdp4_crtc =to_mdp4_crtc (crtc);struct drm_plane *plane; -for_each_plane_on_crtc (crtc, plane) { +drm_atomic_crtc_for_each_plane (plane, crtc) {enum mdp4_pipe pipe_id =mdp4_plane_pipe (plane);int idx = idxs[pipe_id]; mixer_cfg = mixercfg(mixer_cfg, mdp4_crtc->mixer,@@ -221,7 +221,7 @@ static void blend_setup(struct drm_crtc *crtc)mdp4_write (mdp4_kms,REG_MDP4_OVLP_TRANSP_HIGH0 (ovlp),0 );mdp4_write (mdp4_kms,REG_MDP4_OVLP_TRANSP_HIGH1 (ovlp),0 ); -for_each_plane_on_crtc (crtc, plane) { +drm_atomic_crtc_for_each_plane (plane, crtc) {enum mdp4_pipe pipe_id =mdp4_plane_pipe (plane);int idx = idxs[pipe_id];if (idx >0 ) {drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +5
-4@@ -91,7 +91,7 @@ static void crtc_flush_all(struct drm_crtc *crtc)if (!mdp5_crtc->ctl)return ; -for_each_plane_on_crtc (crtc, plane) { +drm_atomic_crtc_for_each_plane (plane, crtc) { flush_mask |=mdp5_plane_get_flush (plane); } flush_mask |=mdp5_ctl_get_flush (mdp5_crtc->ctl);@@ -124,8 +124,9 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file) }spin_unlock_irqrestore (&dev->event_lock, flags); -for_each_plane_on_crtc (crtc, plane) +drm_atomic_crtc_for_each_plane (plane, crtc) {mdp5_plane_complete_flip (plane); + } }static void mdp5_crtc_destroy (struct drm_crtc *crtc)@@ -195,7 +196,7 @@ static void blend_setup(struct drm_crtc *crtc)if (!mdp5_crtc->ctl) goto out; -for_each_plane_on_crtc (crtc, plane) { +drm_atomic_crtc_for_each_plane (plane, crtc) {enum mdp_mixer_stage_id stage =to_mdp5_plane_state (plane->state)->stage;@@ -317,7 +318,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,/* verify that there are not too many planes attached to crtc * and that we don't have conflicting mixer stages: */ -for_each_pending_plane_on_crtc (state->state, crtc, plane) { +drm_atomic_crtc_state_for_each_plane (plane, state) {struct drm_plane_state *pstate;if (cnt >=ARRAY_SIZE (pstates)) {drivers/gpu/drm/msm/msm_kms.h +0
-23@@ -65,27 +65,4 @@ static inline void msm_kms_init(struct msm_kms *kms,struct msm_kms *mdp4_kms_init (struct drm_device *dev);struct msm_kms *mdp5_kms_init (struct drm_device *dev); -/* TODO move these helper iterator macro somewhere common: */ -#define for_each_plane_on_crtc (_crtc, _plane) \ - list_for_each_entry((_plane), &(_crtc)->dev->mode_config.plane_list, head) \ - if ((_plane)->state->crtc == (_crtc)) - -static inline bool -__plane_will_be_attached_to_crtc (struct drm_atomic_state *state, -struct drm_plane *plane,struct drm_crtc *crtc) -{ -int idx =drm_plane_index (plane); - -/* if plane is modified in incoming state, use the new state: */ -if (state->plane_states[idx]) -return state->plane_states[idx]->crtc == crtc; - -/* otherwise, current state: */ -return plane->state->crtc == crtc; -} - -#define for_each_pending_plane_on_crtc (_state, _crtc, _plane) \ - list_for_each_entry((_plane), &(_crtc)->dev->mode_config.plane_list, head) \ - if (__plane_will_be_attached_to_crtc((_state), (_plane), (_crtc))) -#endif /* __MSM_KMS_H__ */ Signature · 1 line
1.9.3
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel