diff options
author | Andrey Grodzovsky <andrey.grodzovsky@amd.com> | 2018-03-29 09:09:39 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-04-03 14:08:44 -0400 |
commit | f7a9ee81a88b83915e7c15895c507abede44b0c5 (patch) | |
tree | 61903e2fc7a93c70bdbd895cf12fda708cba7b31 /drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | |
parent | 073997ccd9dd8eb8015f5371ff0ea85a48814bb4 (diff) |
drm/amdgpu: Add support for SRBM selection v3
Also remove code duplication in write and read regs functions.
This also fixes potential missing unlock in amdgpu_debugfs_regs_write
in case get_user would fail.
v2: Add SRBM mutex locking.
v3: Fix TO counter and fix comment location.
Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 117 |
1 files changed, 40 insertions, 77 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 369beb5041a2..448d69fe3756 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | |||
@@ -64,16 +64,21 @@ int amdgpu_debugfs_add_files(struct amdgpu_device *adev, | |||
64 | 64 | ||
65 | #if defined(CONFIG_DEBUG_FS) | 65 | #if defined(CONFIG_DEBUG_FS) |
66 | 66 | ||
67 | static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, | 67 | |
68 | size_t size, loff_t *pos) | 68 | static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, |
69 | char __user *buf, size_t size, loff_t *pos) | ||
69 | { | 70 | { |
70 | struct amdgpu_device *adev = file_inode(f)->i_private; | 71 | struct amdgpu_device *adev = file_inode(f)->i_private; |
71 | ssize_t result = 0; | 72 | ssize_t result = 0; |
72 | int r; | 73 | int r; |
73 | bool pm_pg_lock, use_bank; | 74 | bool pm_pg_lock, use_bank, use_ring; |
74 | unsigned instance_bank, sh_bank, se_bank; | 75 | unsigned instance_bank, sh_bank, se_bank, me, pipe, queue; |
75 | 76 | ||
76 | if (size & 0x3 || *pos & 0x3) | 77 | pm_pg_lock = use_bank = use_ring = false; |
78 | instance_bank = sh_bank = se_bank = me = pipe = queue = 0; | ||
79 | |||
80 | if (size & 0x3 || *pos & 0x3 || | ||
81 | ((*pos & (1ULL << 62)) && (*pos & (1ULL << 61)))) | ||
77 | return -EINVAL; | 82 | return -EINVAL; |
78 | 83 | ||
79 | /* are we reading registers for which a PG lock is necessary? */ | 84 | /* are we reading registers for which a PG lock is necessary? */ |
@@ -91,8 +96,15 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, | |||
91 | if (instance_bank == 0x3FF) | 96 | if (instance_bank == 0x3FF) |
92 | instance_bank = 0xFFFFFFFF; | 97 | instance_bank = 0xFFFFFFFF; |
93 | use_bank = 1; | 98 | use_bank = 1; |
99 | } else if (*pos & (1ULL << 61)) { | ||
100 | |||
101 | me = (*pos & GENMASK_ULL(33, 24)) >> 24; | ||
102 | pipe = (*pos & GENMASK_ULL(43, 34)) >> 34; | ||
103 | queue = (*pos & GENMASK_ULL(53, 44)) >> 44; | ||
104 | |||
105 | use_ring = 1; | ||
94 | } else { | 106 | } else { |
95 | use_bank = 0; | 107 | use_bank = use_ring = 0; |
96 | } | 108 | } |
97 | 109 | ||
98 | *pos &= (1UL << 22) - 1; | 110 | *pos &= (1UL << 22) - 1; |
@@ -104,6 +116,9 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, | |||
104 | mutex_lock(&adev->grbm_idx_mutex); | 116 | mutex_lock(&adev->grbm_idx_mutex); |
105 | amdgpu_gfx_select_se_sh(adev, se_bank, | 117 | amdgpu_gfx_select_se_sh(adev, se_bank, |
106 | sh_bank, instance_bank); | 118 | sh_bank, instance_bank); |
119 | } else if (use_ring) { | ||
120 | mutex_lock(&adev->srbm_mutex); | ||
121 | amdgpu_gfx_select_me_pipe_q(adev, me, pipe, queue); | ||
107 | } | 122 | } |
108 | 123 | ||
109 | if (pm_pg_lock) | 124 | if (pm_pg_lock) |
@@ -115,8 +130,14 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, | |||
115 | if (*pos > adev->rmmio_size) | 130 | if (*pos > adev->rmmio_size) |
116 | goto end; | 131 | goto end; |
117 | 132 | ||
118 | value = RREG32(*pos >> 2); | 133 | if (read) { |
119 | r = put_user(value, (uint32_t *)buf); | 134 | value = RREG32(*pos >> 2); |
135 | r = put_user(value, (uint32_t *)buf); | ||
136 | } else { | ||
137 | r = get_user(value, (uint32_t *)buf); | ||
138 | if (!r) | ||
139 | WREG32(*pos >> 2, value); | ||
140 | } | ||
120 | if (r) { | 141 | if (r) { |
121 | result = r; | 142 | result = r; |
122 | goto end; | 143 | goto end; |
@@ -132,6 +153,9 @@ end: | |||
132 | if (use_bank) { | 153 | if (use_bank) { |
133 | amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); | 154 | amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); |
134 | mutex_unlock(&adev->grbm_idx_mutex); | 155 | mutex_unlock(&adev->grbm_idx_mutex); |
156 | } else if (use_ring) { | ||
157 | amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0); | ||
158 | mutex_unlock(&adev->srbm_mutex); | ||
135 | } | 159 | } |
136 | 160 | ||
137 | if (pm_pg_lock) | 161 | if (pm_pg_lock) |
@@ -140,78 +164,17 @@ end: | |||
140 | return result; | 164 | return result; |
141 | } | 165 | } |
142 | 166 | ||
167 | |||
168 | static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, | ||
169 | size_t size, loff_t *pos) | ||
170 | { | ||
171 | return amdgpu_debugfs_process_reg_op(true, f, buf, size, pos); | ||
172 | } | ||
173 | |||
143 | static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf, | 174 | static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf, |
144 | size_t size, loff_t *pos) | 175 | size_t size, loff_t *pos) |
145 | { | 176 | { |
146 | struct amdgpu_device *adev = file_inode(f)->i_private; | 177 | return amdgpu_debugfs_process_reg_op(false, f, (char __user *)buf, size, pos); |
147 | ssize_t result = 0; | ||
148 | int r; | ||
149 | bool pm_pg_lock, use_bank; | ||
150 | unsigned instance_bank, sh_bank, se_bank; | ||
151 | |||
152 | if (size & 0x3 || *pos & 0x3) | ||
153 | return -EINVAL; | ||
154 | |||
155 | /* are we reading registers for which a PG lock is necessary? */ | ||
156 | pm_pg_lock = (*pos >> 23) & 1; | ||
157 | |||
158 | if (*pos & (1ULL << 62)) { | ||
159 | se_bank = (*pos & GENMASK_ULL(33, 24)) >> 24; | ||
160 | sh_bank = (*pos & GENMASK_ULL(43, 34)) >> 34; | ||
161 | instance_bank = (*pos & GENMASK_ULL(53, 44)) >> 44; | ||
162 | |||
163 | if (se_bank == 0x3FF) | ||
164 | se_bank = 0xFFFFFFFF; | ||
165 | if (sh_bank == 0x3FF) | ||
166 | sh_bank = 0xFFFFFFFF; | ||
167 | if (instance_bank == 0x3FF) | ||
168 | instance_bank = 0xFFFFFFFF; | ||
169 | use_bank = 1; | ||
170 | } else { | ||
171 | use_bank = 0; | ||
172 | } | ||
173 | |||
174 | *pos &= (1UL << 22) - 1; | ||
175 | |||
176 | if (use_bank) { | ||
177 | if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || | ||
178 | (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines)) | ||
179 | return -EINVAL; | ||
180 | mutex_lock(&adev->grbm_idx_mutex); | ||
181 | amdgpu_gfx_select_se_sh(adev, se_bank, | ||
182 | sh_bank, instance_bank); | ||
183 | } | ||
184 | |||
185 | if (pm_pg_lock) | ||
186 | mutex_lock(&adev->pm.mutex); | ||
187 | |||
188 | while (size) { | ||
189 | uint32_t value; | ||
190 | |||
191 | if (*pos > adev->rmmio_size) | ||
192 | return result; | ||
193 | |||
194 | r = get_user(value, (uint32_t *)buf); | ||
195 | if (r) | ||
196 | return r; | ||
197 | |||
198 | WREG32(*pos >> 2, value); | ||
199 | |||
200 | result += 4; | ||
201 | buf += 4; | ||
202 | *pos += 4; | ||
203 | size -= 4; | ||
204 | } | ||
205 | |||
206 | if (use_bank) { | ||
207 | amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); | ||
208 | mutex_unlock(&adev->grbm_idx_mutex); | ||
209 | } | ||
210 | |||
211 | if (pm_pg_lock) | ||
212 | mutex_unlock(&adev->pm.mutex); | ||
213 | |||
214 | return result; | ||
215 | } | 178 | } |
216 | 179 | ||
217 | static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, | 180 | static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, |