On Mon, Oct 17, 2016 at 02:37:06PM +0200, Maarten Lankhorst wrote: > Signed-off-by: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx> > --- > drivers/gpu/drm/drm_atomic_helper.c | 302 +++++++++++++++++++----------------- > 1 file changed, 157 insertions(+), 145 deletions(-) > > diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c > index fcb6e5b55217..c8aba493fc17 100644 > --- a/drivers/gpu/drm/drm_atomic_helper.c > +++ b/drivers/gpu/drm/drm_atomic_helper.c > @@ -103,7 +103,7 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, > * part of the state. If the same encoder is assigned to multiple > * connectors bail out. > */ > - for_each_connector_in_state(state, connector, conn_state, i) { > + for_each_new_connector_in_state(state, connector, conn_state, i) { > const struct drm_connector_helper_funcs *funcs = connector->helper_private; > struct drm_encoder *new_encoder; > > @@ -238,22 +238,22 @@ steal_encoder(struct drm_atomic_state *state, > { > struct drm_crtc_state *crtc_state; > struct drm_connector *connector; > - struct drm_connector_state *connector_state; > + struct drm_connector_state *old_connector_state, *new_connector_state; > int i; > > - for_each_connector_in_state(state, connector, connector_state, i) { > + for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) { > struct drm_crtc *encoder_crtc; > > - if (connector_state->best_encoder != encoder) > + if (new_connector_state->best_encoder != encoder) > continue; > > - encoder_crtc = connector->state->crtc; > + encoder_crtc = old_connector_state->crtc; > > DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], stealing it\n", > encoder->base.id, encoder->name, > encoder_crtc->base.id, encoder_crtc->name); > > - set_best_encoder(state, connector_state, NULL); > + set_best_encoder(state, new_connector_state, NULL); > > crtc_state = drm_atomic_get_existing_crtc_state(state, encoder_crtc); > crtc_state->connectors_changed = true; > @@ -265,7 +265,8 @@ steal_encoder(struct drm_atomic_state *state, > static int > update_connector_routing(struct drm_atomic_state *state, > struct drm_connector *connector, > - struct drm_connector_state *connector_state) > + struct drm_connector_state *old_connector_state, > + struct drm_connector_state *new_connector_state) > { > const struct drm_connector_helper_funcs *funcs; > struct drm_encoder *new_encoder; > @@ -275,24 +276,24 @@ update_connector_routing(struct drm_atomic_state *state, > connector->base.id, > connector->name); > > - if (connector->state->crtc != connector_state->crtc) { > - if (connector->state->crtc) { > - crtc_state = drm_atomic_get_existing_crtc_state(state, connector->state->crtc); > + if (old_connector_state->crtc != new_connector_state->crtc) { > + if (old_connector_state->crtc) { > + crtc_state = drm_atomic_get_existing_crtc_state(state, old_connector_state->crtc); > crtc_state->connectors_changed = true; > } > > - if (connector_state->crtc) { > - crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc); > + if (new_connector_state->crtc) { > + crtc_state = drm_atomic_get_existing_crtc_state(state, new_connector_state->crtc); > crtc_state->connectors_changed = true; > } > } > > - if (!connector_state->crtc) { > + if (!new_connector_state->crtc) { > DRM_DEBUG_ATOMIC("Disabling [CONNECTOR:%d:%s]\n", > connector->base.id, > connector->name); > > - set_best_encoder(state, connector_state, NULL); > + set_best_encoder(state, new_connector_state, NULL); > > return 0; > } > @@ -301,7 +302,7 @@ update_connector_routing(struct drm_atomic_state *state, > > if (funcs->atomic_best_encoder) > new_encoder = funcs->atomic_best_encoder(connector, > - connector_state); > + new_connector_state); > else if (funcs->best_encoder) > new_encoder = funcs->best_encoder(connector); > else > @@ -314,33 +315,33 @@ update_connector_routing(struct drm_atomic_state *state, > return -EINVAL; > } > > - if (!drm_encoder_crtc_ok(new_encoder, connector_state->crtc)) { > + if (!drm_encoder_crtc_ok(new_encoder, new_connector_state->crtc)) { > DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d]\n", > new_encoder->base.id, > new_encoder->name, > - connector_state->crtc->base.id); > + new_connector_state->crtc->base.id); > return -EINVAL; > } > > - if (new_encoder == connector_state->best_encoder) { > - set_best_encoder(state, connector_state, new_encoder); > + if (new_encoder == new_connector_state->best_encoder) { > + set_best_encoder(state, new_connector_state, new_encoder); > > DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d:%s]\n", > connector->base.id, > connector->name, > new_encoder->base.id, > new_encoder->name, > - connector_state->crtc->base.id, > - connector_state->crtc->name); > + new_connector_state->crtc->base.id, > + new_connector_state->crtc->name); > > return 0; > } > > steal_encoder(state, new_encoder); > > - set_best_encoder(state, connector_state, new_encoder); > + set_best_encoder(state, new_connector_state, new_encoder); > > - crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc); > + crtc_state = drm_atomic_get_existing_crtc_state(state, new_connector_state->crtc); > crtc_state->connectors_changed = true; > > DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n", > @@ -348,8 +349,8 @@ update_connector_routing(struct drm_atomic_state *state, > connector->name, > new_encoder->base.id, > new_encoder->name, > - connector_state->crtc->base.id, > - connector_state->crtc->name); > + new_connector_state->crtc->base.id, > + new_connector_state->crtc->name); > > return 0; > } > @@ -364,7 +365,7 @@ mode_fixup(struct drm_atomic_state *state) > int i; > bool ret; > > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { > if (!crtc_state->mode_changed && > !crtc_state->connectors_changed) > continue; > @@ -372,7 +373,7 @@ mode_fixup(struct drm_atomic_state *state) > drm_mode_copy(&crtc_state->adjusted_mode, &crtc_state->mode); > } > > - for_each_connector_in_state(state, connector, conn_state, i) { > + for_each_new_connector_in_state(state, connector, conn_state, i) { > const struct drm_encoder_helper_funcs *funcs; > struct drm_encoder *encoder; > > @@ -417,7 +418,7 @@ mode_fixup(struct drm_atomic_state *state) > } > } > > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { > const struct drm_crtc_helper_funcs *funcs; > > if (!crtc_state->enable) > @@ -476,19 +477,19 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, > struct drm_atomic_state *state) > { > struct drm_crtc *crtc; > - struct drm_crtc_state *crtc_state; > + struct drm_crtc_state *old_crtc_state, *new_crtc_state; > struct drm_connector *connector; > - struct drm_connector_state *connector_state; > + struct drm_connector_state *old_connector_state, *new_connector_state; > int i, ret; > > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > - if (!drm_mode_equal(&crtc->state->mode, &crtc_state->mode)) { > + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { > + if (!drm_mode_equal(&old_crtc_state->mode, &new_crtc_state->mode)) { > DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode changed\n", > crtc->base.id, crtc->name); > - crtc_state->mode_changed = true; > + new_crtc_state->mode_changed = true; > } > > - if (crtc->state->enable != crtc_state->enable) { > + if (old_crtc_state->enable != new_crtc_state->enable) { > DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enable changed\n", > crtc->base.id, crtc->name); > > @@ -500,8 +501,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, > * The other way around is true as well. enable != 0 > * iff connectors are attached and a mode is set. > */ > - crtc_state->mode_changed = true; > - crtc_state->connectors_changed = true; > + new_crtc_state->mode_changed = true; > + new_crtc_state->connectors_changed = true; > } > } > > @@ -509,14 +510,15 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, > if (ret) > return ret; > > - for_each_connector_in_state(state, connector, connector_state, i) { > + for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) { > /* > * This only sets crtc->connectors_changed for routing changes, > * drivers must set crtc->connectors_changed themselves when > * connector properties need to be updated. > */ > ret = update_connector_routing(state, connector, > - connector_state); > + old_connector_state, > + new_connector_state); > if (ret) > return ret; > } > @@ -527,28 +529,28 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, > * configuration. This must be done before calling mode_fixup in case a > * crtc only changed its mode but has the same set of connectors. > */ > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { > bool has_connectors = > - !!crtc_state->connector_mask; > + !!new_crtc_state->connector_mask; > > /* > * We must set ->active_changed after walking connectors for > * otherwise an update that only changes active would result in > * a full modeset because update_connector_routing force that. > */ > - if (crtc->state->active != crtc_state->active) { > + if (old_crtc_state->active != new_crtc_state->active) { > DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active changed\n", > crtc->base.id, crtc->name); > - crtc_state->active_changed = true; > + new_crtc_state->active_changed = true; > } > > - if (!drm_atomic_crtc_needs_modeset(crtc_state)) > + if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) > continue; > > DRM_DEBUG_ATOMIC("[CRTC:%d:%s] needs all connectors, enable: %c, active: %c\n", > crtc->base.id, crtc->name, > - crtc_state->enable ? 'y' : 'n', > - crtc_state->active ? 'y' : 'n'); > + new_crtc_state->enable ? 'y' : 'n', > + new_crtc_state->active ? 'y' : 'n'); > > ret = drm_atomic_add_affected_connectors(state, crtc); > if (ret != 0) > @@ -558,7 +560,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, > if (ret != 0) > return ret; > > - if (crtc_state->enable != has_connectors) { > + if (new_crtc_state->enable != has_connectors) { > DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled/connectors mismatch\n", > crtc->base.id, crtc->name); > > @@ -599,7 +601,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev, > if (ret) > return ret; > > - for_each_plane_in_state(state, plane, plane_state, i) { > + for_each_new_plane_in_state(state, plane, plane_state, i) { > const struct drm_plane_helper_funcs *funcs; > > funcs = plane->helper_private; > @@ -617,7 +619,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev, > } > } > > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { > const struct drm_crtc_helper_funcs *funcs; > > funcs = crtc->helper_private; Up to here everything runs in the check phase, so the straightforwared s/state/new_state/ and s/foo->state/old_state/ looks correct. > @@ -678,12 +680,12 @@ static void > disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) > { > struct drm_connector *connector; > - struct drm_connector_state *old_conn_state; > + struct drm_connector_state *old_conn_state, *new_conn_state; > struct drm_crtc *crtc; > - struct drm_crtc_state *old_crtc_state; > + struct drm_crtc_state *old_crtc_state, *new_crtc_state; > int i; > > - for_each_connector_in_state(old_state, connector, old_conn_state, i) { > + for_each_oldnew_connector_in_state(old_state, connector, old_conn_state, new_conn_state, i) { > const struct drm_encoder_helper_funcs *funcs; > struct drm_encoder *encoder; > > @@ -720,7 +722,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) > > /* Right function depends upon target state. */ > if (funcs) { > - if (connector->state->crtc && funcs->prepare) > + if (new_conn_state->crtc && funcs->prepare) > funcs->prepare(encoder); > else if (funcs->disable) > funcs->disable(encoder); > @@ -731,11 +733,11 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) > drm_bridge_post_disable(encoder->bridge); > } > > - for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { > + for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { > const struct drm_crtc_helper_funcs *funcs; > > /* Shut down everything that needs a full modeset. */ > - if (!drm_atomic_crtc_needs_modeset(crtc->state)) > + if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) > continue; > > if (!old_crtc_state->active) > @@ -748,7 +750,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) > > > /* Right function depends upon target state. */ > - if (crtc->state->enable && funcs->prepare) > + if (new_crtc_state->enable && funcs->prepare) > funcs->prepare(crtc); > else if (funcs->atomic_disable) > funcs->atomic_disable(crtc, old_crtc_state); And this sucker is executed after we've swapped the state, so we need to do the s/foo->state/new_state/ replacement. Looks correct to me. Not sure how worried I should be that we might forget some foo->state dereference somewhere. Should we try rename that pointer to something else to make sure we've caught everything? > @@ -777,13 +779,13 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, > struct drm_atomic_state *old_state) > { > struct drm_connector *connector; > - struct drm_connector_state *old_conn_state; > + struct drm_connector_state *old_conn_state, *new_conn_state; > struct drm_crtc *crtc; > - struct drm_crtc_state *old_crtc_state; > + struct drm_crtc_state *crtc_state; > int i; > > /* clear out existing links and update dpms */ > - for_each_connector_in_state(old_state, connector, old_conn_state, i) { > + for_each_oldnew_connector_in_state(old_state, connector, old_conn_state, new_conn_state, i) { > if (connector->encoder) { > WARN_ON(!connector->encoder->crtc); > > @@ -791,7 +793,7 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, > connector->encoder = NULL; > } > > - crtc = connector->state->crtc; > + crtc = new_conn_state->crtc; > if ((!crtc && old_conn_state->crtc) || > (crtc && drm_atomic_crtc_needs_modeset(crtc->state))) { ^^^^^^^^^^^^ Like this guy here. That should be new_crtc_state, no? > struct drm_property *dpms_prop = > @@ -808,23 +810,23 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, > } > > /* set new links */ > - for_each_connector_in_state(old_state, connector, old_conn_state, i) { > - if (!connector->state->crtc) > + for_each_new_connector_in_state(old_state, connector, new_conn_state, i) { > + if (!new_conn_state->crtc) > continue; > > - if (WARN_ON(!connector->state->best_encoder)) > + if (WARN_ON(!new_conn_state->best_encoder)) > continue; > > - connector->encoder = connector->state->best_encoder; > - connector->encoder->crtc = connector->state->crtc; > + connector->encoder = new_conn_state->best_encoder; > + connector->encoder->crtc = new_conn_state->crtc; > } > > /* set legacy state in the crtc structure */ > - for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { > + for_each_new_crtc_in_state(old_state, crtc, crtc_state, i) { > struct drm_plane *primary = crtc->primary; > > - crtc->mode = crtc->state->mode; > - crtc->enabled = crtc->state->enable; > + crtc->mode = crtc_state->mode; > + crtc->enabled = crtc_state->enable; > > if (drm_atomic_get_existing_plane_state(old_state, primary) && > primary->state->crtc == crtc) { ^^^^^^^^^^^^^^ new_plane_state or something? > @@ -832,9 +834,9 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, > crtc->y = primary->state->src_y >> 16; > } > > - if (crtc->state->enable) > + if (crtc_state->enable) > drm_calc_timestamping_constants(crtc, > - &crtc->state->adjusted_mode); > + &crtc_state->adjusted_mode); > } > } > EXPORT_SYMBOL(drm_atomic_helper_update_legacy_modeset_state); > @@ -843,20 +845,20 @@ static void > crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) > { > struct drm_crtc *crtc; > - struct drm_crtc_state *old_crtc_state; > + struct drm_crtc_state *crtc_state; > struct drm_connector *connector; > - struct drm_connector_state *old_conn_state; > + struct drm_connector_state *conn_state; > int i; > > - for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { > + for_each_new_crtc_in_state(old_state, crtc, crtc_state, i) { > const struct drm_crtc_helper_funcs *funcs; > > - if (!crtc->state->mode_changed) > + if (!crtc_state->mode_changed) > continue; > > funcs = crtc->helper_private; > > - if (crtc->state->enable && funcs->mode_set_nofb) { > + if (crtc_state->enable && funcs->mode_set_nofb) { > DRM_DEBUG_ATOMIC("modeset on [CRTC:%d:%s]\n", > crtc->base.id, crtc->name); > > @@ -864,18 +866,18 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) > } > } > > - for_each_connector_in_state(old_state, connector, old_conn_state, i) { > + for_each_new_connector_in_state(old_state, connector, conn_state, i) { > const struct drm_encoder_helper_funcs *funcs; > struct drm_crtc_state *new_crtc_state; > struct drm_encoder *encoder; > struct drm_display_mode *mode, *adjusted_mode; > > - if (!connector->state->best_encoder) > + if (!conn_state->best_encoder) > continue; > > - encoder = connector->state->best_encoder; > + encoder = conn_state->best_encoder; > funcs = encoder->helper_private; > - new_crtc_state = connector->state->crtc->state; > + new_crtc_state = conn_state->crtc->state; > mode = &new_crtc_state->mode; > adjusted_mode = &new_crtc_state->adjusted_mode; > > @@ -891,7 +893,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) > */ > if (funcs && funcs->atomic_mode_set) { > funcs->atomic_mode_set(encoder, new_crtc_state, > - connector->state); > + conn_state); > } else if (funcs && funcs->mode_set) { > funcs->mode_set(encoder, mode, adjusted_mode); > } > @@ -943,24 +945,24 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, > struct drm_atomic_state *old_state) > { > struct drm_crtc *crtc; > - struct drm_crtc_state *old_crtc_state; > + struct drm_crtc_state *crtc_state; > struct drm_connector *connector; > - struct drm_connector_state *old_conn_state; > + struct drm_connector_state *conn_state; > int i; > > - for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { > + for_each_new_crtc_in_state(old_state, crtc, crtc_state, i) { > const struct drm_crtc_helper_funcs *funcs; > > /* Need to filter out CRTCs where only planes change. */ > - if (!drm_atomic_crtc_needs_modeset(crtc->state)) > + if (!drm_atomic_crtc_needs_modeset(crtc_state)) > continue; > > - if (!crtc->state->active) > + if (!crtc_state->active) > continue; > > funcs = crtc->helper_private; > > - if (crtc->state->enable) { > + if (crtc_state->enable) { > DRM_DEBUG_ATOMIC("enabling [CRTC:%d:%s]\n", > crtc->base.id, crtc->name); > > @@ -971,18 +973,18 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, > } > } > > - for_each_connector_in_state(old_state, connector, old_conn_state, i) { > + for_each_new_connector_in_state(old_state, connector, conn_state, i) { > const struct drm_encoder_helper_funcs *funcs; > struct drm_encoder *encoder; > > - if (!connector->state->best_encoder) > + if (!conn_state->best_encoder) > continue; > > - if (!connector->state->crtc->state->active || > - !drm_atomic_crtc_needs_modeset(connector->state->crtc->state)) > + if (!conn_state->crtc->state->active || > + !drm_atomic_crtc_needs_modeset(conn_state->crtc->state)) More foo->state stuff remaining > continue; > > - encoder = connector->state->best_encoder; > + encoder = conn_state->best_encoder; > funcs = encoder->helper_private; > > DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n", > @@ -1027,10 +1029,7 @@ int drm_atomic_helper_wait_for_fences(struct drm_device *dev, > struct drm_plane_state *plane_state; > int i, ret; > > - for_each_plane_in_state(state, plane, plane_state, i) { > - if (!pre_swap) > - plane_state = plane->state; > - > + for_each_new_plane_in_state(state, plane, plane_state, i) { Nice. Can we kill the pre_swap flag now? Hmm, no, we pass it to dma_fence_wait() to indicate interruptible vs. not. Maybe we can rename it to convey its only remaining function better? > if (!plane_state->fence) > continue; > > @@ -1072,15 +1071,15 @@ bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev, > struct drm_crtc *crtc) > { > struct drm_plane *plane; > - struct drm_plane_state *old_plane_state; > + struct drm_plane_state *old_plane_state, *new_plane_state; > int i; > > - for_each_plane_in_state(old_state, plane, old_plane_state, i) { > - if (plane->state->crtc != crtc && > + for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) { > + if (new_plane_state->crtc != crtc && > old_plane_state->crtc != crtc) > continue; > > - if (plane->state->fb != old_plane_state->fb) > + if (new_plane_state->fb != old_plane_state->fb) > return true; > } This thing was totally broken, but I guess now it actually should work regardless of when we call it. Cool. I was actually wonder if we manage to plumb the old+new state everywhere maybe we could kill off some of the need_whatever flags? Not quite sure. > > @@ -1104,21 +1103,21 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, > struct drm_atomic_state *old_state) > { > struct drm_crtc *crtc; > - struct drm_crtc_state *old_crtc_state; > + struct drm_crtc_state *old_crtc_state, *new_crtc_state; > int i, ret; > > - for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { > + /* Legacy cursor ioctls are completely unsynced, and userspace > + * relies on that (by doing tons of cursor updates). */ > + if (old_state->legacy_cursor_update) > + return; > + We seem to have a change of behaviour here. Should be in a separate patch if we actually want it. > + for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { > /* No one cares about the old state, so abuse it for tracking > * and store whether we hold a vblank reference (and should do a > * vblank wait) in the ->enable boolean. */ > old_crtc_state->enable = false; > > - if (!crtc->state->enable) > - continue; > - > - /* Legacy cursor ioctls are completely unsynced, and userspace > - * relies on that (by doing tons of cursor updates). */ > - if (old_state->legacy_cursor_update) > + if (!new_crtc_state->enable) > continue; > > if (!drm_atomic_helper_framebuffer_changed(dev, > @@ -1133,7 +1132,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, > old_crtc_state->last_vblank_count = drm_crtc_vblank_count(crtc); > } > > - for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { > + for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) { > if (!old_crtc_state->enable) > continue; > I think pretty much evething up to this point (from the last checkpoint) is executed after swapping the state, with drm_atomic_helper_framebuffer_changed() being the oddball that might be called from anywhere. > @@ -1432,11 +1431,11 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, > bool nonblock) > { > struct drm_crtc *crtc; > - struct drm_crtc_state *crtc_state; > + struct drm_crtc_state *old_crtc_state, *crtc_state; > struct drm_crtc_commit *commit; > int i, ret; > > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) { > commit = kzalloc(sizeof(*commit), GFP_KERNEL); > if (!commit) > return -ENOMEM; > @@ -1457,7 +1456,7 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, > /* Drivers only send out events when at least either current or > * new CRTC state is active. Complete right away if everything > * stays off. */ > - if (!crtc->state->active && !crtc_state->active) { > + if (!old_crtc_state->active && !crtc_state->active) { > complete_all(&commit->flip_done); > continue; > } This guy is pre state swap. Looks correct. > @@ -1521,7 +1520,7 @@ void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *state) > int i; > long ret; > > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { This is post state swap, but we don't actually use the new or the old state here, so this looks fine. > spin_lock(&crtc->commit_lock); > commit = preceeding_commit(crtc); > if (commit) > @@ -1572,13 +1571,13 @@ void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *state) > struct drm_crtc_commit *commit; > int i; > > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { > commit = state->crtcs[i].commit; > if (!commit) > continue; > > /* backend must have consumed any event by now */ > - WARN_ON(crtc->state->event); > + WARN_ON(crtc_state->event); Post swap. Looks correct. > spin_lock(&crtc->commit_lock); > complete_all(&commit->hw_done); > spin_unlock(&crtc->commit_lock); > @@ -1605,7 +1604,7 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *state) > int i; > long ret; > > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { Post swap. State not used, so fine. > commit = state->crtcs[i].commit; > if (WARN_ON(!commit)) > continue; > @@ -1658,7 +1657,7 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev, > struct drm_plane_state *plane_state; > int ret, i, j; > > - for_each_plane_in_state(state, plane, plane_state, i) { > + for_each_new_plane_in_state(state, plane, plane_state, i) { > const struct drm_plane_helper_funcs *funcs; > > funcs = plane->helper_private; > @@ -1676,7 +1675,7 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev, > return 0; > > fail: > - for_each_plane_in_state(state, plane, plane_state, j) { > + for_each_new_plane_in_state(state, plane, plane_state, j) { Pre swap stuff. Fine. > const struct drm_plane_helper_funcs *funcs; > > if (j >= i) > @@ -1746,14 +1745,14 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, > uint32_t flags) > { > struct drm_crtc *crtc; > - struct drm_crtc_state *old_crtc_state; > + struct drm_crtc_state *old_crtc_state, *new_crtc_state; > struct drm_plane *plane; > - struct drm_plane_state *old_plane_state; > + struct drm_plane_state *old_plane_state, *new_plane_state; > int i; > bool active_only = flags & DRM_PLANE_COMMIT_ACTIVE_ONLY; > bool no_disable = flags & DRM_PLANE_COMMIT_NO_DISABLE_AFTER_MODESET; > > - for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { > + for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { > const struct drm_crtc_helper_funcs *funcs; > > funcs = crtc->helper_private; > @@ -1761,13 +1760,13 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, > if (!funcs || !funcs->atomic_begin) > continue; > > - if (active_only && !crtc->state->active) > + if (active_only && !new_crtc_state->active) > continue; > > funcs->atomic_begin(crtc, old_crtc_state); > } > > - for_each_plane_in_state(old_state, plane, old_plane_state, i) { > + for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) { > const struct drm_plane_helper_funcs *funcs; > bool disabling; > > @@ -1786,7 +1785,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, > * CRTC to avoid skipping planes being disabled on an > * active CRTC. > */ > - if (!disabling && !plane_crtc_active(plane->state)) > + if (!disabling && !plane_crtc_active(new_plane_state)) > continue; > if (disabling && !plane_crtc_active(old_plane_state)) > continue; > @@ -1805,12 +1804,12 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, > continue; > > funcs->atomic_disable(plane, old_plane_state); > - } else if (plane->state->crtc || disabling) { > + } else if (new_plane_state->crtc || disabling) { > funcs->atomic_update(plane, old_plane_state); > } > } > > - for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { > + for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { > const struct drm_crtc_helper_funcs *funcs; > > funcs = crtc->helper_private; > @@ -1818,7 +1817,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, > if (!funcs || !funcs->atomic_flush) > continue; > > - if (active_only && !crtc->state->active) > + if (active_only && !new_crtc_state->active) > continue; > > funcs->atomic_flush(crtc, old_crtc_state); > @@ -1945,12 +1944,19 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev, > struct drm_atomic_state *old_state) > { > struct drm_plane *plane; > - struct drm_plane_state *plane_state; > + struct drm_plane_state *plane_state, *new_plane_state; > int i; > > - for_each_plane_in_state(old_state, plane, plane_state, i) { > + for_each_oldnew_plane_in_state(old_state, plane, plane_state, new_plane_state, i) { > const struct drm_plane_helper_funcs *funcs; > > + /* > + * This might be called before swapping when commit is aborted, > + * in which case we have to free the new state. > + */ > + if (plane_state == plane->state) > + plane_state = new_plane_state; Oh dear. Can we make this nicer somehow? I can't actually see any use like that currently. Am I blind? I was wondering if we should add some kind of asserts to a bunch of these functions to make sure they are called during the correct phase of the operation. We could track the progress in the top level state I guess. > + > if (!drm_atomic_helper_framebuffer_changed(dev, old_state, plane_state->crtc)) > continue; > > @@ -1998,15 +2004,15 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, > int i; > long ret; > struct drm_connector *connector; > - struct drm_connector_state *conn_state; > + struct drm_connector_state *old_conn_state, *new_conn_state; > struct drm_crtc *crtc; > - struct drm_crtc_state *crtc_state; > + struct drm_crtc_state *old_crtc_state, *new_crtc_state; > struct drm_plane *plane; > - struct drm_plane_state *plane_state; > + struct drm_plane_state *old_plane_state, *new_plane_state; > struct drm_crtc_commit *commit; > > if (stall) { > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { > spin_lock(&crtc->commit_lock); > commit = list_first_entry_or_null(&crtc->commit_list, > struct drm_crtc_commit, commit_entry); > @@ -2026,16 +2032,20 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, > } > } > > - for_each_connector_in_state(state, connector, conn_state, i) { > - connector->state->state = state; > - swap(state->connectors[i].state, connector->state); > - connector->state->state = NULL; > + for_each_oldnew_connector_in_state(state, connector, old_conn_state, new_conn_state, i) { > + old_conn_state->state = state; > + new_conn_state->state = NULL; > + > + state->connectors[i].state = old_conn_state; > + connector->state = new_conn_state; > } > > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > - crtc->state->state = state; > - swap(state->crtcs[i].state, crtc->state); > - crtc->state->state = NULL; > + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { > + old_crtc_state->state = state; > + new_crtc_state->state = NULL; > + > + state->crtcs[i].state = old_crtc_state; > + crtc->state = new_crtc_state; > > if (state->crtcs[i].commit) { > spin_lock(&crtc->commit_lock); > @@ -2047,10 +2057,12 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, > } > } > > - for_each_plane_in_state(state, plane, plane_state, i) { > - plane->state->state = state; > - swap(state->planes[i].state, plane->state); > - plane->state->state = NULL; > + for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { > + old_plane_state->state = state; > + new_plane_state->state = NULL; > + > + state->planes[i].state = old_plane_state; > + plane->state = new_plane_state; > } > } lgtm > EXPORT_SYMBOL(drm_atomic_helper_swap_state); > @@ -2248,7 +2260,7 @@ static int update_output_state(struct drm_atomic_state *state, > if (ret) > return ret; > > - for_each_connector_in_state(state, connector, conn_state, i) { > + for_each_new_connector_in_state(state, connector, conn_state, i) { > if (conn_state->crtc == set->crtc) { > ret = drm_atomic_set_crtc_for_connector(conn_state, > NULL); > @@ -2270,7 +2282,7 @@ static int update_output_state(struct drm_atomic_state *state, > return ret; > } > > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { > /* Don't update ->enable for the CRTC in the set_config request, > * since a mismatch would indicate a bug in the upper layers. > * The actual modeset code later on will catch any Building up the new state. Looks correct. Phew! Apart from some of the lingering foo->state dereferences and the change in behaviour for legacy cursors, and the slight oddballness in the plane_cleanup() I didn't spot anything wrong. This thing could use a commit message I think. Could at least lay out the basic rules on the foo->state/foo_state vs. old_state/new_state replacements. Might help someone understand it who doesn't know so much about the current state swapping mechanism. -- Ville Syrjälä Intel OTC _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx