aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2398-drm-amd-display-Don-t-leak-dc_stream_state.patch
blob: 22b5ddcb2ad3ca60f1e3f1e6cbbe045411c80020 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
From b87c748082d1fcb252e653d1b18ab539fe7a12d5 Mon Sep 17 00:00:00 2001
From: Darren Salt <devspam@moreofthesa.me.uk>
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:
        [<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>
---
 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