From b87c748082d1fcb252e653d1b18ab539fe7a12d5 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Tue, 12 Sep 2017 17:10:25 +0100 Subject: [PATCH 2398/4131] drm/amd/display: Don't leak dc_stream_state. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Noticed while playing “Valley”, which was causing some 8MB of leakage per second. kmemleak listed many entries looking like this: unreferenced object 0xffff8802c2951800 (size 1024): comm "Xorg", pid 2982, jiffies 4297410155 (age 392.787s) hex dump (first 32 bytes): 00 50 f9 0c 04 88 ff ff 98 08 00 00 00 00 00 00 .P.............. 80 07 00 00 00 00 00 00 58 00 00 00 2c 00 00 00 ........X...,... backtrace: [] create_object+0x13c/0x261 [] kmemleak_alloc+0x20/0x3c [] slab_post_alloc_hook+0x42/0x52 [] kmem_cache_alloc+0x67/0x76 [] dc_create_stream_for_sink+0x24/0x1cf [] create_stream_for_sink+0x6f/0x295 [] dm_update_crtcs_state+0xa6/0x268 [] amdgpu_dm_atomic_check+0x9a/0x314 [] drm_atomic_check_only+0x17a/0x42d [] drm_atomic_commit+0x13/0x4b [] drm_atomic_connector_commit_dpms+0xcb/0xe8 [] drm_mode_obj_set_property_ioctl+0xe6/0x1e3 [] drm_mode_connector_property_set_ioctl+0x2b/0x2d [] drm_ioctl_kernel+0x64/0x9d [] drm_ioctl+0x230/0x316 [] amdgpu_drm_ioctl+0x4b/0x7d v2: also handle break statements. Signed-off-by: Darren Salt Reviewed-by: Harry Wentland --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 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 ade9998..cc96b73 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4575,6 +4575,7 @@ static int dm_update_crtcs_state(struct dc *dc, int i; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + struct dc_stream_state *new_stream; int ret = 0; /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ @@ -4582,10 +4583,10 @@ static int dm_update_crtcs_state(struct dc *dc, for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_dm_connector *aconnector = NULL; - struct dc_stream_state *new_stream = NULL; struct drm_connector_state *conn_state = NULL; struct dm_connector_state *dm_conn_state = NULL; + new_stream = NULL; old_acrtc_state = to_dm_crtc_state(crtc->state); new_acrtc_state = to_dm_crtc_state(crtc_state); @@ -4634,7 +4635,7 @@ static int dm_update_crtcs_state(struct dc *dc, if (!drm_atomic_crtc_needs_modeset(crtc_state)) - continue; + goto next_crtc; #if !defined(OS_NAME_RHEL_7_2) DRM_DEBUG_KMS( @@ -4654,7 +4655,7 @@ static int dm_update_crtcs_state(struct dc *dc, if (!enable) { if (!old_acrtc_state->stream) - continue; + goto next_crtc; DRM_DEBUG_KMS("Disabling DRM crtc: %d\n", crtc->base.id); @@ -4665,7 +4666,7 @@ static int dm_update_crtcs_state(struct dc *dc, dm_state->context, old_acrtc_state->stream)) { ret = -EINVAL; - break; + goto fail; } dc_stream_release(old_acrtc_state->stream); @@ -4676,7 +4677,7 @@ static int dm_update_crtcs_state(struct dc *dc, } else {/* Add stream for any updated/enabled CRTC */ if (modereset_required(crtc_state)) - continue; + goto next_crtc; if (modeset_required(crtc_state, new_stream, old_acrtc_state->stream)) { @@ -4694,19 +4695,25 @@ static int dm_update_crtcs_state(struct dc *dc, dm_state->context, new_acrtc_state->stream)) { ret = -EINVAL; - break; + goto fail; } *lock_and_validation_needed = true; } } +next_crtc: /* Release extra reference */ if (new_stream) dc_stream_release(new_stream); } return ret; + +fail: + if (new_stream) + dc_stream_release(new_stream); + return ret; } static int dm_update_planes_state(struct dc *dc, -- 2.7.4