[PATCH 6/7] drm/amd/display: Drop dm_determine_update_type_for_commit
Rodrigo Siqueira
Rodrigo.Siqueira at amd.com
Wed Aug 5 20:48:58 UTC 2020
Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira at amd.com>
On 07/30, Nicholas Kazlauskas wrote:
> [Why]
> This was added in the past to solve the issue of not knowing when
> to stall for medium and full updates in DM.
>
> Since DC is ultimately decides what requires bandwidth changes we
> wanted to make use of it directly to determine this.
>
> The problem is that we can't actually pass any of the stream or surface
> updates into DC global validation, so we don't actually check if the new
> configuration is valid - we just validate the old existing config
> instead and stall for outstanding commits to finish.
>
> There's also the problem of grabbing the DRM private object for
> pageflips which can lead to page faults in the case where commits
> execute out of order and free a DRM private object state that was
> still required for commit tail.
>
> [How]
> Now that we reset the plane in DM with the same conditions DC checks
> we can have planes go through DC validation and we know when we need
> to check and stall based on whether the stream or planes changed.
>
> We mark lock_and_validation_needed whenever we've done this, so just
> go back to using that instead of dm_determine_update_type_for_commit.
>
> Since we'll skip resetting the plane for a pageflip we will no longer
> grab the DRM private object for pageflips as well, avoiding the
> page fault issued caused by pageflipping under load with commits
> executing out of order.
>
> Cc: Harry Wentland <harry.wentland at amd.com>
> Cc: Bhawanpreet Lakha <Bhawanpreet.Lakha at amd.com>
> Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas at amd.com>
> ---
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 199 ++----------------
> 1 file changed, 17 insertions(+), 182 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 2cbb29199e61..59829ec81694 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -8542,161 +8542,6 @@ static int dm_update_plane_state(struct dc *dc,
> return ret;
> }
>
> -static int
> -dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm,
> - struct drm_atomic_state *state,
> - enum surface_update_type *out_type)
> -{
> - struct dc *dc = dm->dc;
> - struct dm_atomic_state *dm_state = NULL, *old_dm_state = NULL;
> - int i, j, num_plane, ret = 0;
> - struct drm_plane_state *old_plane_state, *new_plane_state;
> - struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state;
> - struct drm_crtc *new_plane_crtc;
> - struct drm_plane *plane;
> -
> - struct drm_crtc *crtc;
> - struct drm_crtc_state *new_crtc_state, *old_crtc_state;
> - struct dm_crtc_state *new_dm_crtc_state, *old_dm_crtc_state;
> - struct dc_stream_status *status = NULL;
> - enum surface_update_type update_type = UPDATE_TYPE_FAST;
> - struct surface_info_bundle {
> - struct dc_surface_update surface_updates[MAX_SURFACES];
> - struct dc_plane_info plane_infos[MAX_SURFACES];
> - struct dc_scaling_info scaling_infos[MAX_SURFACES];
> - struct dc_flip_addrs flip_addrs[MAX_SURFACES];
> - struct dc_stream_update stream_update;
> - } *bundle;
> -
> - bundle = kzalloc(sizeof(*bundle), GFP_KERNEL);
> -
> - if (!bundle) {
> - DRM_ERROR("Failed to allocate update bundle\n");
> - /* Set type to FULL to avoid crashing in DC*/
> - update_type = UPDATE_TYPE_FULL;
> - goto cleanup;
> - }
> -
> - for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
> -
> - memset(bundle, 0, sizeof(struct surface_info_bundle));
> -
> - new_dm_crtc_state = to_dm_crtc_state(new_crtc_state);
> - old_dm_crtc_state = to_dm_crtc_state(old_crtc_state);
> - num_plane = 0;
> -
> - if (new_dm_crtc_state->stream != old_dm_crtc_state->stream) {
> - update_type = UPDATE_TYPE_FULL;
> - goto cleanup;
> - }
> -
> - if (!new_dm_crtc_state->stream)
> - continue;
> -
> - for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, j) {
> - struct dc_plane_info *plane_info = &bundle->plane_infos[num_plane];
> - struct dc_flip_addrs *flip_addr = &bundle->flip_addrs[num_plane];
> - struct dc_scaling_info *scaling_info = &bundle->scaling_infos[num_plane];
> -
> - new_plane_crtc = new_plane_state->crtc;
> - new_dm_plane_state = to_dm_plane_state(new_plane_state);
> - old_dm_plane_state = to_dm_plane_state(old_plane_state);
> -
> - if (plane->type == DRM_PLANE_TYPE_CURSOR)
> - continue;
> -
> - if (new_dm_plane_state->dc_state != old_dm_plane_state->dc_state) {
> - update_type = UPDATE_TYPE_FULL;
> - goto cleanup;
> - }
> -
> - if (crtc != new_plane_crtc)
> - continue;
> -
> - bundle->surface_updates[num_plane].surface =
> - new_dm_plane_state->dc_state;
> -
> - if (new_crtc_state->mode_changed) {
> - bundle->stream_update.dst = new_dm_crtc_state->stream->dst;
> - bundle->stream_update.src = new_dm_crtc_state->stream->src;
> - }
> -
> - if (new_crtc_state->color_mgmt_changed) {
> - bundle->surface_updates[num_plane].gamma =
> - new_dm_plane_state->dc_state->gamma_correction;
> - bundle->surface_updates[num_plane].in_transfer_func =
> - new_dm_plane_state->dc_state->in_transfer_func;
> - bundle->surface_updates[num_plane].gamut_remap_matrix =
> - &new_dm_plane_state->dc_state->gamut_remap_matrix;
> - bundle->stream_update.gamut_remap =
> - &new_dm_crtc_state->stream->gamut_remap_matrix;
> - bundle->stream_update.output_csc_transform =
> - &new_dm_crtc_state->stream->csc_color_matrix;
> - bundle->stream_update.out_transfer_func =
> - new_dm_crtc_state->stream->out_transfer_func;
> - }
> -
> - ret = fill_dc_scaling_info(new_plane_state,
> - scaling_info);
> - if (ret)
> - goto cleanup;
> -
> - bundle->surface_updates[num_plane].scaling_info = scaling_info;
> -
> - if (new_plane_state->fb) {
> - ret = fill_dc_plane_info_and_addr(
> - dm->adev, new_plane_state,
> - new_dm_plane_state->tiling_flags,
> - plane_info, &flip_addr->address,
> - new_dm_plane_state->tmz_surface, false);
> - if (ret)
> - goto cleanup;
> -
> - bundle->surface_updates[num_plane].plane_info = plane_info;
> - bundle->surface_updates[num_plane].flip_addr = flip_addr;
> - }
> -
> - num_plane++;
> - }
> -
> - if (num_plane == 0)
> - continue;
> -
> - ret = dm_atomic_get_state(state, &dm_state);
> - if (ret)
> - goto cleanup;
> -
> - old_dm_state = dm_atomic_get_old_state(state);
> - if (!old_dm_state) {
> - ret = -EINVAL;
> - goto cleanup;
> - }
> -
> - status = dc_stream_get_status_from_state(old_dm_state->context,
> - new_dm_crtc_state->stream);
> - bundle->stream_update.stream = new_dm_crtc_state->stream;
> - /*
> - * TODO: DC modifies the surface during this call so we need
> - * to lock here - find a way to do this without locking.
> - */
> - mutex_lock(&dm->dc_lock);
> - update_type = dc_check_update_surfaces_for_stream(
> - dc, bundle->surface_updates, num_plane,
> - &bundle->stream_update, status);
> - mutex_unlock(&dm->dc_lock);
> -
> - if (update_type > UPDATE_TYPE_MED) {
> - update_type = UPDATE_TYPE_FULL;
> - goto cleanup;
> - }
> - }
> -
> -cleanup:
> - kfree(bundle);
> -
> - *out_type = update_type;
> - return ret;
> -}
> #if defined(CONFIG_DRM_AMD_DC_DCN)
> static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc)
> {
> @@ -8737,8 +8582,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
> * acquired. For full updates case which removes/adds/updates streams on one
> * CRTC while flipping on another CRTC, acquiring global lock will guarantee
> * that any such full update commit will wait for completion of any outstanding
> - * flip using DRMs synchronization events. See
> - * dm_determine_update_type_for_commit()
> + * flip using DRMs synchronization events.
> *
> * Note that DM adds the affected connectors for all CRTCs in state, when that
> * might not seem necessary. This is because DC stream creation requires the
> @@ -8759,15 +8603,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
> struct drm_crtc_state *old_crtc_state, *new_crtc_state;
> struct drm_plane *plane;
> struct drm_plane_state *old_plane_state, *new_plane_state;
> - enum surface_update_type update_type = UPDATE_TYPE_FAST;
> - enum surface_update_type overall_update_type = UPDATE_TYPE_FAST;
> enum dc_status status;
> int ret, i;
> -
> - /*
> - * This bool will be set for true for any modeset/reset
> - * or plane update which implies non fast surface update.
> - */
> bool lock_and_validation_needed = false;
>
> ret = drm_atomic_helper_check_modeset(dev, state);
> @@ -8961,27 +8798,23 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
> if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state))
> continue;
>
> - overall_update_type = UPDATE_TYPE_FULL;
> lock_and_validation_needed = true;
> }
>
> - ret = dm_determine_update_type_for_commit(&adev->dm, state, &update_type);
> - if (ret)
> - goto fail;
> -
> - if (overall_update_type < update_type)
> - overall_update_type = update_type;
> -
> - /*
> - * lock_and_validation_needed was an old way to determine if we need to set
> - * the global lock. Leaving it in to check if we broke any corner cases
> - * lock_and_validation_needed true = UPDATE_TYPE_FULL or UPDATE_TYPE_MED
> - * lock_and_validation_needed false = UPDATE_TYPE_FAST
> + /**
> + * Streams and planes are reset when there are changes that affect
> + * bandwidth. Anything that affects bandwidth needs to go through
> + * DC global validation to ensure that the configuration can be applied
> + * to hardware.
> + *
> + * We have to currently stall out here in atomic_check for outstanding
> + * commits to finish in this case because our IRQ handlers reference
> + * DRM state directly - we can end up disabling interrupts too early
> + * if we don't.
> + *
> + * TODO: Remove this stall and drop DM state private objects.
> */
> - if (lock_and_validation_needed && overall_update_type <= UPDATE_TYPE_FAST)
> - WARN(1, "Global lock should be Set, overall_update_type should be UPDATE_TYPE_MED or UPDATE_TYPE_FULL");
> -
> - if (overall_update_type > UPDATE_TYPE_FAST) {
> + if (lock_and_validation_needed) {
> ret = dm_atomic_get_state(state, &dm_state);
> if (ret)
> goto fail;
> @@ -9063,7 +8896,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
> struct dm_crtc_state *dm_new_crtc_state =
> to_dm_crtc_state(new_crtc_state);
>
> - dm_new_crtc_state->update_type = (int)overall_update_type;
> + dm_new_crtc_state->update_type = lock_and_validation_needed ?
> + UPDATE_TYPE_FULL :
> + UPDATE_TYPE_FAST;
> }
>
> /* Must be success */
> --
> 2.25.1
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&data=02%7C01%7CRodrigo.Siqueira%40amd.com%7C0b11d89281b84b13c2ba08d834c866ba%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637317382661579264&sdata=0%2BiC8Fx2pHp5cCo2p5TovGSRrrbnYH867lad%2B5ZeXqM%3D&reserved=0
--
Rodrigo Siqueira
https://siqueira.tech
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20200805/b34fd0f1/attachment-0001.sig>
More information about the dri-devel
mailing list