From dce3dc28b1e34cdb37f5de5d8949cda4ac5599e0 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 20 Feb 2018 15:46:09 -0500 Subject: [PATCH 3743/4131] drm/amd/display: Fix memleaks when atomic check fails. While checking plane states for updates during atomic check, we create dc_plane_states in preparation. These dc states should be freed if something errors. Although the input transfer function is also freed by dc_plane_state_release(), we should free it (on error) under the same scope as where it is created. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Conflicts: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c Change-Id: I5af43a6d41efed4369ae641e0491b17e489e9a77 --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 40 ++++++++++++++++------- 1 file changed, 28 insertions(+), 12 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 4652515..a56522e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1991,7 +1991,11 @@ static int fill_plane_attributes(struct amdgpu_device *adev, * every time. */ ret = amdgpu_dm_set_degamma_lut(crtc_state, dc_plane_state); - + if (ret) { + dc_transfer_func_release(dc_plane_state->in_transfer_func); + dc_plane_state->in_transfer_func = NULL; + } + return ret; } @@ -4850,6 +4854,7 @@ static int dm_update_planes_state(struct dc *dc, *lock_and_validation_needed = true; } else { /* Add new planes */ + struct dc_plane_state *dc_new_plane_state; if (drm_atomic_plane_disabling(plane->state, new_plane_state)) continue; @@ -4867,35 +4872,46 @@ static int dm_update_planes_state(struct dc *dc, continue; WARN_ON(dm_new_plane_state->dc_state); - - dm_new_plane_state->dc_state = dc_create_plane_state(dc); - - DRM_DEBUG_DRIVER("Enabling DRM plane: %d on DRM crtc %d\n", - plane->base.id, new_plane_crtc->base.id); - - if (!dm_new_plane_state->dc_state) { + + dc_new_plane_state = dc_create_plane_state(dc); + if (!dc_new_plane_state) { ret = -EINVAL; return ret; } + + DRM_DEBUG_DRIVER("Enabling DRM plane: %d on DRM crtc %d\n", + plane->base.id, new_plane_crtc->base.id); ret = fill_plane_attributes( new_plane_crtc->dev->dev_private, - dm_new_plane_state->dc_state, + dc_new_plane_state, new_plane_state, new_crtc_state); - if (ret) + if (ret) { + dc_plane_state_release(dc_new_plane_state); return ret; + } + /* + * Any atomic check errors that occur after this will + * not need a release. The plane state will be attached + * to the stream, and therefore part of the atomic + * state. It'll be released when the atomic state is + * cleaned. + */ if (!dc_add_plane_to_context( dc, dm_new_crtc_state->stream, - dm_new_plane_state->dc_state, + dc_new_plane_state, dm_state->context)) { - + + dc_plane_state_release(dc_new_plane_state); ret = -EINVAL; return ret; } + dm_new_plane_state->dc_state = dc_new_plane_state; + /* Tell DC to do a full surface update every time there * is a plane change. Inefficient, but works for now. */ -- 2.7.4