diff options
author | Darren Salt <devspam@moreofthesa.me.uk> | 2017-09-12 12:10:25 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-09-26 18:17:07 -0400 |
commit | 9635b75436e5f536831c810c715f3ae24a5bbbae (patch) | |
tree | cdf706671e13f79a9e1d7ac0eecfe4cb65e5131c /drivers/gpu/drm/amd/display | |
parent | 62f555377f972c206c69c6acc93d91f2baec9a26 (diff) |
drm/amd/display: Don't leak dc_stream_state.
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:
[<ffffffff810cd4c3>] create_object+0x13c/0x261
[<ffffffff815abdc2>] kmemleak_alloc+0x20/0x3c
[<ffffffff810cad1d>] slab_post_alloc_hook+0x42/0x52
[<ffffffff810cb8e0>] kmem_cache_alloc+0x67/0x76
[<ffffffff813bbb54>] dc_create_stream_for_sink+0x24/0x1cf
[<ffffffff81373aaa>] create_stream_for_sink+0x6f/0x295
[<ffffffff81373dc2>] dm_update_crtcs_state+0xa6/0x268
[<ffffffff8137401e>] amdgpu_dm_atomic_check+0x9a/0x314
[<ffffffff812ac3dd>] drm_atomic_check_only+0x17a/0x42d
[<ffffffff812ac6a3>] drm_atomic_commit+0x13/0x4b
[<ffffffff812ad1a5>] drm_atomic_connector_commit_dpms+0xcb/0xe8
[<ffffffff812b1238>] drm_mode_obj_set_property_ioctl+0xe6/0x1e3
[<ffffffff812b027b>] drm_mode_connector_property_set_ioctl+0x2b/0x2d
[<ffffffff8129f427>] drm_ioctl_kernel+0x64/0x9d
[<ffffffff8129f6a2>] drm_ioctl+0x230/0x316
[<ffffffff812ca4d3>] amdgpu_drm_ioctl+0x4b/0x7d
v2: also handle break statements.
Signed-off-by: Darren Salt <devspam@moreofthesa.me.uk>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display')
-rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 20 |
1 files changed, 14 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 193a634f46e6..4f1e31cd4cbe 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |||
@@ -4357,6 +4357,7 @@ static int dm_update_crtcs_state( | |||
4357 | int i; | 4357 | int i; |
4358 | struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; | 4358 | struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; |
4359 | struct dm_atomic_state *dm_state = to_dm_atomic_state(state); | 4359 | struct dm_atomic_state *dm_state = to_dm_atomic_state(state); |
4360 | struct dc_stream_state *new_stream; | ||
4360 | int ret = 0; | 4361 | int ret = 0; |
4361 | 4362 | ||
4362 | /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ | 4363 | /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ |
@@ -4364,10 +4365,11 @@ static int dm_update_crtcs_state( | |||
4364 | for_each_crtc_in_state(state, crtc, crtc_state, i) { | 4365 | for_each_crtc_in_state(state, crtc, crtc_state, i) { |
4365 | struct amdgpu_crtc *acrtc = NULL; | 4366 | struct amdgpu_crtc *acrtc = NULL; |
4366 | struct amdgpu_connector *aconnector = NULL; | 4367 | struct amdgpu_connector *aconnector = NULL; |
4367 | struct dc_stream_state *new_stream = NULL; | ||
4368 | struct drm_connector_state *conn_state = NULL; | 4368 | struct drm_connector_state *conn_state = NULL; |
4369 | struct dm_connector_state *dm_conn_state = NULL; | 4369 | struct dm_connector_state *dm_conn_state = NULL; |
4370 | 4370 | ||
4371 | new_stream = NULL; | ||
4372 | |||
4371 | old_acrtc_state = to_dm_crtc_state(crtc->state); | 4373 | old_acrtc_state = to_dm_crtc_state(crtc->state); |
4372 | new_acrtc_state = to_dm_crtc_state(crtc_state); | 4374 | new_acrtc_state = to_dm_crtc_state(crtc_state); |
4373 | acrtc = to_amdgpu_crtc(crtc); | 4375 | acrtc = to_amdgpu_crtc(crtc); |
@@ -4415,7 +4417,7 @@ static int dm_update_crtcs_state( | |||
4415 | 4417 | ||
4416 | 4418 | ||
4417 | if (!drm_atomic_crtc_needs_modeset(crtc_state)) | 4419 | if (!drm_atomic_crtc_needs_modeset(crtc_state)) |
4418 | continue; | 4420 | goto next_crtc; |
4419 | 4421 | ||
4420 | DRM_DEBUG_KMS( | 4422 | DRM_DEBUG_KMS( |
4421 | "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " | 4423 | "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " |
@@ -4433,7 +4435,7 @@ static int dm_update_crtcs_state( | |||
4433 | if (!enable) { | 4435 | if (!enable) { |
4434 | 4436 | ||
4435 | if (!old_acrtc_state->stream) | 4437 | if (!old_acrtc_state->stream) |
4436 | continue; | 4438 | goto next_crtc; |
4437 | 4439 | ||
4438 | DRM_DEBUG_KMS("Disabling DRM crtc: %d\n", | 4440 | DRM_DEBUG_KMS("Disabling DRM crtc: %d\n", |
4439 | crtc->base.id); | 4441 | crtc->base.id); |
@@ -4444,7 +4446,7 @@ static int dm_update_crtcs_state( | |||
4444 | dm_state->context, | 4446 | dm_state->context, |
4445 | old_acrtc_state->stream)) { | 4447 | old_acrtc_state->stream)) { |
4446 | ret = -EINVAL; | 4448 | ret = -EINVAL; |
4447 | break; | 4449 | goto fail; |
4448 | } | 4450 | } |
4449 | 4451 | ||
4450 | dc_stream_release(old_acrtc_state->stream); | 4452 | dc_stream_release(old_acrtc_state->stream); |
@@ -4455,7 +4457,7 @@ static int dm_update_crtcs_state( | |||
4455 | } else {/* Add stream for any updated/enabled CRTC */ | 4457 | } else {/* Add stream for any updated/enabled CRTC */ |
4456 | 4458 | ||
4457 | if (modereset_required(crtc_state)) | 4459 | if (modereset_required(crtc_state)) |
4458 | continue; | 4460 | goto next_crtc; |
4459 | 4461 | ||
4460 | if (modeset_required(crtc_state, new_stream, | 4462 | if (modeset_required(crtc_state, new_stream, |
4461 | old_acrtc_state->stream)) { | 4463 | old_acrtc_state->stream)) { |
@@ -4473,19 +4475,25 @@ static int dm_update_crtcs_state( | |||
4473 | dm_state->context, | 4475 | dm_state->context, |
4474 | new_acrtc_state->stream)) { | 4476 | new_acrtc_state->stream)) { |
4475 | ret = -EINVAL; | 4477 | ret = -EINVAL; |
4476 | break; | 4478 | goto fail; |
4477 | } | 4479 | } |
4478 | 4480 | ||
4479 | *lock_and_validation_needed = true; | 4481 | *lock_and_validation_needed = true; |
4480 | } | 4482 | } |
4481 | } | 4483 | } |
4482 | 4484 | ||
4485 | next_crtc: | ||
4483 | /* Release extra reference */ | 4486 | /* Release extra reference */ |
4484 | if (new_stream) | 4487 | if (new_stream) |
4485 | dc_stream_release(new_stream); | 4488 | dc_stream_release(new_stream); |
4486 | } | 4489 | } |
4487 | 4490 | ||
4488 | return ret; | 4491 | return ret; |
4492 | |||
4493 | fail: | ||
4494 | if (new_stream) | ||
4495 | dc_stream_release(new_stream); | ||
4496 | return ret; | ||
4489 | } | 4497 | } |
4490 | 4498 | ||
4491 | static int dm_update_planes_state( | 4499 | static int dm_update_planes_state( |