1 | /* |
2 | * Copyright 2008 Advanced Micro Devices, Inc. |
3 | * Copyright 2008 Red Hat Inc. |
4 | * Copyright 2009 Jerome Glisse. |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the "Software"), |
8 | * to deal in the Software without restriction, including without limitation |
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
10 | * and/or sell copies of the Software, and to permit persons to whom the |
11 | * Software is furnished to do so, subject to the following conditions: |
12 | * |
13 | * The above copyright notice and this permission notice shall be included in |
14 | * all copies or substantial portions of the Software. |
15 | * |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
22 | * OTHER DEALINGS IN THE SOFTWARE. |
23 | * |
24 | */ |
25 | |
26 | #include <linux/kthread.h> |
27 | #include <drm/drmP.h> |
28 | #include <linux/debugfs.h> |
29 | #include "amdgpu.h" |
30 | |
31 | /** |
32 | * amdgpu_debugfs_add_files - Add simple debugfs entries |
33 | * |
34 | * @adev: Device to attach debugfs entries to |
35 | * @files: Array of function callbacks that respond to reads |
36 | * @nfiles: Number of callbacks to register |
37 | * |
38 | */ |
39 | int amdgpu_debugfs_add_files(struct amdgpu_device *adev, |
40 | const struct drm_info_list *files, |
41 | unsigned nfiles) |
42 | { |
43 | unsigned i; |
44 | |
45 | for (i = 0; i < adev->debugfs_count; i++) { |
46 | if (adev->debugfs[i].files == files) { |
47 | /* Already registered */ |
48 | return 0; |
49 | } |
50 | } |
51 | |
52 | i = adev->debugfs_count + 1; |
53 | if (i > AMDGPU_DEBUGFS_MAX_COMPONENTS) { |
54 | DRM_ERROR("Reached maximum number of debugfs components.\n" ); |
55 | DRM_ERROR("Report so we increase " |
56 | "AMDGPU_DEBUGFS_MAX_COMPONENTS.\n" ); |
57 | return -EINVAL; |
58 | } |
59 | adev->debugfs[adev->debugfs_count].files = files; |
60 | adev->debugfs[adev->debugfs_count].num_files = nfiles; |
61 | adev->debugfs_count = i; |
62 | #if defined(CONFIG_DEBUG_FS) |
63 | drm_debugfs_create_files(files, nfiles, |
64 | adev->ddev->primary->debugfs_root, |
65 | adev->ddev->primary); |
66 | #endif |
67 | return 0; |
68 | } |
69 | |
70 | #if defined(CONFIG_DEBUG_FS) |
71 | |
72 | /** |
73 | * amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes |
74 | * |
75 | * @read: True if reading |
76 | * @f: open file handle |
77 | * @buf: User buffer to write/read to |
78 | * @size: Number of bytes to write/read |
79 | * @pos: Offset to seek to |
80 | * |
81 | * This debugfs entry has special meaning on the offset being sought. |
82 | * Various bits have different meanings: |
83 | * |
84 | * Bit 62: Indicates a GRBM bank switch is needed |
85 | * Bit 61: Indicates a SRBM bank switch is needed (implies bit 62 is |
86 | * zero) |
87 | * Bits 24..33: The SE or ME selector if needed |
88 | * Bits 34..43: The SH (or SA) or PIPE selector if needed |
89 | * Bits 44..53: The INSTANCE (or CU/WGP) or QUEUE selector if needed |
90 | * |
91 | * Bit 23: Indicates that the PM power gating lock should be held |
92 | * This is necessary to read registers that might be |
93 | * unreliable during a power gating transistion. |
94 | * |
95 | * The lower bits are the BYTE offset of the register to read. This |
96 | * allows reading multiple registers in a single call and having |
97 | * the returned size reflect that. |
98 | */ |
99 | static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, |
100 | char __user *buf, size_t size, loff_t *pos) |
101 | { |
102 | struct amdgpu_device *adev = file_inode(f)->i_private; |
103 | ssize_t result = 0; |
104 | int r; |
105 | bool pm_pg_lock, use_bank, use_ring; |
106 | unsigned instance_bank, sh_bank, se_bank, me, pipe, queue; |
107 | |
108 | pm_pg_lock = use_bank = use_ring = false; |
109 | instance_bank = sh_bank = se_bank = me = pipe = queue = 0; |
110 | |
111 | if (size & 0x3 || *pos & 0x3 || |
112 | ((*pos & (1ULL << 62)) && (*pos & (1ULL << 61)))) |
113 | return -EINVAL; |
114 | |
115 | /* are we reading registers for which a PG lock is necessary? */ |
116 | pm_pg_lock = (*pos >> 23) & 1; |
117 | |
118 | if (*pos & (1ULL << 62)) { |
119 | se_bank = (*pos & GENMASK_ULL(33, 24)) >> 24; |
120 | sh_bank = (*pos & GENMASK_ULL(43, 34)) >> 34; |
121 | instance_bank = (*pos & GENMASK_ULL(53, 44)) >> 44; |
122 | |
123 | if (se_bank == 0x3FF) |
124 | se_bank = 0xFFFFFFFF; |
125 | if (sh_bank == 0x3FF) |
126 | sh_bank = 0xFFFFFFFF; |
127 | if (instance_bank == 0x3FF) |
128 | instance_bank = 0xFFFFFFFF; |
129 | use_bank = 1; |
130 | } else if (*pos & (1ULL << 61)) { |
131 | |
132 | me = (*pos & GENMASK_ULL(33, 24)) >> 24; |
133 | pipe = (*pos & GENMASK_ULL(43, 34)) >> 34; |
134 | queue = (*pos & GENMASK_ULL(53, 44)) >> 44; |
135 | |
136 | use_ring = 1; |
137 | } else { |
138 | use_bank = use_ring = 0; |
139 | } |
140 | |
141 | *pos &= (1UL << 22) - 1; |
142 | |
143 | if (use_bank) { |
144 | if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || |
145 | (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines)) |
146 | return -EINVAL; |
147 | mutex_lock(&adev->grbm_idx_mutex); |
148 | amdgpu_gfx_select_se_sh(adev, se_bank, |
149 | sh_bank, instance_bank); |
150 | } else if (use_ring) { |
151 | mutex_lock(&adev->srbm_mutex); |
152 | amdgpu_gfx_select_me_pipe_q(adev, me, pipe, queue); |
153 | } |
154 | |
155 | if (pm_pg_lock) |
156 | mutex_lock(&adev->pm.mutex); |
157 | |
158 | while (size) { |
159 | uint32_t value; |
160 | |
161 | if (read) { |
162 | value = RREG32(*pos >> 2); |
163 | r = put_user(value, (uint32_t *)buf); |
164 | } else { |
165 | r = get_user(value, (uint32_t *)buf); |
166 | if (!r) |
167 | WREG32(*pos >> 2, value); |
168 | } |
169 | if (r) { |
170 | result = r; |
171 | goto end; |
172 | } |
173 | |
174 | result += 4; |
175 | buf += 4; |
176 | *pos += 4; |
177 | size -= 4; |
178 | } |
179 | |
180 | end: |
181 | if (use_bank) { |
182 | amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); |
183 | mutex_unlock(&adev->grbm_idx_mutex); |
184 | } else if (use_ring) { |
185 | amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0); |
186 | mutex_unlock(&adev->srbm_mutex); |
187 | } |
188 | |
189 | if (pm_pg_lock) |
190 | mutex_unlock(&adev->pm.mutex); |
191 | |
192 | return result; |
193 | } |
194 | |
195 | /** |
196 | * amdgpu_debugfs_regs_read - Callback for reading MMIO registers |
197 | */ |
198 | static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, |
199 | size_t size, loff_t *pos) |
200 | { |
201 | return amdgpu_debugfs_process_reg_op(true, f, buf, size, pos); |
202 | } |
203 | |
204 | /** |
205 | * amdgpu_debugfs_regs_write - Callback for writing MMIO registers |
206 | */ |
207 | static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf, |
208 | size_t size, loff_t *pos) |
209 | { |
210 | return amdgpu_debugfs_process_reg_op(false, f, (char __user *)buf, size, pos); |
211 | } |
212 | |
213 | |
214 | /** |
215 | * amdgpu_debugfs_regs_pcie_read - Read from a PCIE register |
216 | * |
217 | * @f: open file handle |
218 | * @buf: User buffer to store read data in |
219 | * @size: Number of bytes to read |
220 | * @pos: Offset to seek to |
221 | * |
222 | * The lower bits are the BYTE offset of the register to read. This |
223 | * allows reading multiple registers in a single call and having |
224 | * the returned size reflect that. |
225 | */ |
226 | static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, |
227 | size_t size, loff_t *pos) |
228 | { |
229 | struct amdgpu_device *adev = file_inode(f)->i_private; |
230 | ssize_t result = 0; |
231 | int r; |
232 | |
233 | if (size & 0x3 || *pos & 0x3) |
234 | return -EINVAL; |
235 | |
236 | while (size) { |
237 | uint32_t value; |
238 | |
239 | value = RREG32_PCIE(*pos >> 2); |
240 | r = put_user(value, (uint32_t *)buf); |
241 | if (r) |
242 | return r; |
243 | |
244 | result += 4; |
245 | buf += 4; |
246 | *pos += 4; |
247 | size -= 4; |
248 | } |
249 | |
250 | return result; |
251 | } |
252 | |
253 | /** |
254 | * amdgpu_debugfs_regs_pcie_write - Write to a PCIE register |
255 | * |
256 | * @f: open file handle |
257 | * @buf: User buffer to write data from |
258 | * @size: Number of bytes to write |
259 | * @pos: Offset to seek to |
260 | * |
261 | * The lower bits are the BYTE offset of the register to write. This |
262 | * allows writing multiple registers in a single call and having |
263 | * the returned size reflect that. |
264 | */ |
265 | static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user *buf, |
266 | size_t size, loff_t *pos) |
267 | { |
268 | struct amdgpu_device *adev = file_inode(f)->i_private; |
269 | ssize_t result = 0; |
270 | int r; |
271 | |
272 | if (size & 0x3 || *pos & 0x3) |
273 | return -EINVAL; |
274 | |
275 | while (size) { |
276 | uint32_t value; |
277 | |
278 | r = get_user(value, (uint32_t *)buf); |
279 | if (r) |
280 | return r; |
281 | |
282 | WREG32_PCIE(*pos >> 2, value); |
283 | |
284 | result += 4; |
285 | buf += 4; |
286 | *pos += 4; |
287 | size -= 4; |
288 | } |
289 | |
290 | return result; |
291 | } |
292 | |
293 | /** |
294 | * amdgpu_debugfs_regs_didt_read - Read from a DIDT register |
295 | * |
296 | * @f: open file handle |
297 | * @buf: User buffer to store read data in |
298 | * @size: Number of bytes to read |
299 | * @pos: Offset to seek to |
300 | * |
301 | * The lower bits are the BYTE offset of the register to read. This |
302 | * allows reading multiple registers in a single call and having |
303 | * the returned size reflect that. |
304 | */ |
305 | static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, |
306 | size_t size, loff_t *pos) |
307 | { |
308 | struct amdgpu_device *adev = file_inode(f)->i_private; |
309 | ssize_t result = 0; |
310 | int r; |
311 | |
312 | if (size & 0x3 || *pos & 0x3) |
313 | return -EINVAL; |
314 | |
315 | while (size) { |
316 | uint32_t value; |
317 | |
318 | value = RREG32_DIDT(*pos >> 2); |
319 | r = put_user(value, (uint32_t *)buf); |
320 | if (r) |
321 | return r; |
322 | |
323 | result += 4; |
324 | buf += 4; |
325 | *pos += 4; |
326 | size -= 4; |
327 | } |
328 | |
329 | return result; |
330 | } |
331 | |
332 | /** |
333 | * amdgpu_debugfs_regs_didt_write - Write to a DIDT register |
334 | * |
335 | * @f: open file handle |
336 | * @buf: User buffer to write data from |
337 | * @size: Number of bytes to write |
338 | * @pos: Offset to seek to |
339 | * |
340 | * The lower bits are the BYTE offset of the register to write. This |
341 | * allows writing multiple registers in a single call and having |
342 | * the returned size reflect that. |
343 | */ |
344 | static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user *buf, |
345 | size_t size, loff_t *pos) |
346 | { |
347 | struct amdgpu_device *adev = file_inode(f)->i_private; |
348 | ssize_t result = 0; |
349 | int r; |
350 | |
351 | if (size & 0x3 || *pos & 0x3) |
352 | return -EINVAL; |
353 | |
354 | while (size) { |
355 | uint32_t value; |
356 | |
357 | r = get_user(value, (uint32_t *)buf); |
358 | if (r) |
359 | return r; |
360 | |
361 | WREG32_DIDT(*pos >> 2, value); |
362 | |
363 | result += 4; |
364 | buf += 4; |
365 | *pos += 4; |
366 | size -= 4; |
367 | } |
368 | |
369 | return result; |
370 | } |
371 | |
372 | /** |
373 | * amdgpu_debugfs_regs_smc_read - Read from a SMC register |
374 | * |
375 | * @f: open file handle |
376 | * @buf: User buffer to store read data in |
377 | * @size: Number of bytes to read |
378 | * @pos: Offset to seek to |
379 | * |
380 | * The lower bits are the BYTE offset of the register to read. This |
381 | * allows reading multiple registers in a single call and having |
382 | * the returned size reflect that. |
383 | */ |
384 | static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, |
385 | size_t size, loff_t *pos) |
386 | { |
387 | struct amdgpu_device *adev = file_inode(f)->i_private; |
388 | ssize_t result = 0; |
389 | int r; |
390 | |
391 | if (size & 0x3 || *pos & 0x3) |
392 | return -EINVAL; |
393 | |
394 | while (size) { |
395 | uint32_t value; |
396 | |
397 | value = RREG32_SMC(*pos); |
398 | r = put_user(value, (uint32_t *)buf); |
399 | if (r) |
400 | return r; |
401 | |
402 | result += 4; |
403 | buf += 4; |
404 | *pos += 4; |
405 | size -= 4; |
406 | } |
407 | |
408 | return result; |
409 | } |
410 | |
411 | /** |
412 | * amdgpu_debugfs_regs_smc_write - Write to a SMC register |
413 | * |
414 | * @f: open file handle |
415 | * @buf: User buffer to write data from |
416 | * @size: Number of bytes to write |
417 | * @pos: Offset to seek to |
418 | * |
419 | * The lower bits are the BYTE offset of the register to write. This |
420 | * allows writing multiple registers in a single call and having |
421 | * the returned size reflect that. |
422 | */ |
423 | static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *buf, |
424 | size_t size, loff_t *pos) |
425 | { |
426 | struct amdgpu_device *adev = file_inode(f)->i_private; |
427 | ssize_t result = 0; |
428 | int r; |
429 | |
430 | if (size & 0x3 || *pos & 0x3) |
431 | return -EINVAL; |
432 | |
433 | while (size) { |
434 | uint32_t value; |
435 | |
436 | r = get_user(value, (uint32_t *)buf); |
437 | if (r) |
438 | return r; |
439 | |
440 | WREG32_SMC(*pos, value); |
441 | |
442 | result += 4; |
443 | buf += 4; |
444 | *pos += 4; |
445 | size -= 4; |
446 | } |
447 | |
448 | return result; |
449 | } |
450 | |
451 | /** |
452 | * amdgpu_debugfs_gca_config_read - Read from gfx config data |
453 | * |
454 | * @f: open file handle |
455 | * @buf: User buffer to store read data in |
456 | * @size: Number of bytes to read |
457 | * @pos: Offset to seek to |
458 | * |
459 | * This file is used to access configuration data in a somewhat |
460 | * stable fashion. The format is a series of DWORDs with the first |
461 | * indicating which revision it is. New content is appended to the |
462 | * end so that older software can still read the data. |
463 | */ |
464 | |
465 | static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf, |
466 | size_t size, loff_t *pos) |
467 | { |
468 | struct amdgpu_device *adev = file_inode(f)->i_private; |
469 | ssize_t result = 0; |
470 | int r; |
471 | uint32_t *config, no_regs = 0; |
472 | |
473 | if (size & 0x3 || *pos & 0x3) |
474 | return -EINVAL; |
475 | |
476 | config = kmalloc_array(256, sizeof(*config), GFP_KERNEL); |
477 | if (!config) |
478 | return -ENOMEM; |
479 | |
480 | /* version, increment each time something is added */ |
481 | config[no_regs++] = 3; |
482 | config[no_regs++] = adev->gfx.config.max_shader_engines; |
483 | config[no_regs++] = adev->gfx.config.max_tile_pipes; |
484 | config[no_regs++] = adev->gfx.config.max_cu_per_sh; |
485 | config[no_regs++] = adev->gfx.config.max_sh_per_se; |
486 | config[no_regs++] = adev->gfx.config.max_backends_per_se; |
487 | config[no_regs++] = adev->gfx.config.max_texture_channel_caches; |
488 | config[no_regs++] = adev->gfx.config.max_gprs; |
489 | config[no_regs++] = adev->gfx.config.max_gs_threads; |
490 | config[no_regs++] = adev->gfx.config.max_hw_contexts; |
491 | config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_frontend; |
492 | config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_backend; |
493 | config[no_regs++] = adev->gfx.config.sc_hiz_tile_fifo_size; |
494 | config[no_regs++] = adev->gfx.config.sc_earlyz_tile_fifo_size; |
495 | config[no_regs++] = adev->gfx.config.num_tile_pipes; |
496 | config[no_regs++] = adev->gfx.config.backend_enable_mask; |
497 | config[no_regs++] = adev->gfx.config.mem_max_burst_length_bytes; |
498 | config[no_regs++] = adev->gfx.config.mem_row_size_in_kb; |
499 | config[no_regs++] = adev->gfx.config.shader_engine_tile_size; |
500 | config[no_regs++] = adev->gfx.config.num_gpus; |
501 | config[no_regs++] = adev->gfx.config.multi_gpu_tile_size; |
502 | config[no_regs++] = adev->gfx.config.mc_arb_ramcfg; |
503 | config[no_regs++] = adev->gfx.config.gb_addr_config; |
504 | config[no_regs++] = adev->gfx.config.num_rbs; |
505 | |
506 | /* rev==1 */ |
507 | config[no_regs++] = adev->rev_id; |
508 | config[no_regs++] = adev->pg_flags; |
509 | config[no_regs++] = adev->cg_flags; |
510 | |
511 | /* rev==2 */ |
512 | config[no_regs++] = adev->family; |
513 | config[no_regs++] = adev->external_rev_id; |
514 | |
515 | /* rev==3 */ |
516 | config[no_regs++] = adev->pdev->device; |
517 | config[no_regs++] = adev->pdev->revision; |
518 | config[no_regs++] = adev->pdev->subsystem_device; |
519 | config[no_regs++] = adev->pdev->subsystem_vendor; |
520 | |
521 | while (size && (*pos < no_regs * 4)) { |
522 | uint32_t value; |
523 | |
524 | value = config[*pos >> 2]; |
525 | r = put_user(value, (uint32_t *)buf); |
526 | if (r) { |
527 | kfree(config); |
528 | return r; |
529 | } |
530 | |
531 | result += 4; |
532 | buf += 4; |
533 | *pos += 4; |
534 | size -= 4; |
535 | } |
536 | |
537 | kfree(config); |
538 | return result; |
539 | } |
540 | |
541 | /** |
542 | * amdgpu_debugfs_sensor_read - Read from the powerplay sensors |
543 | * |
544 | * @f: open file handle |
545 | * @buf: User buffer to store read data in |
546 | * @size: Number of bytes to read |
547 | * @pos: Offset to seek to |
548 | * |
549 | * The offset is treated as the BYTE address of one of the sensors |
550 | * enumerated in amd/include/kgd_pp_interface.h under the |
551 | * 'amd_pp_sensors' enumeration. For instance to read the UVD VCLK |
552 | * you would use the offset 3 * 4 = 12. |
553 | */ |
554 | static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, |
555 | size_t size, loff_t *pos) |
556 | { |
557 | struct amdgpu_device *adev = file_inode(f)->i_private; |
558 | int idx, x, outsize, r, valuesize; |
559 | uint32_t values[16]; |
560 | |
561 | if (size & 3 || *pos & 0x3) |
562 | return -EINVAL; |
563 | |
564 | if (!adev->pm.dpm_enabled) |
565 | return -EINVAL; |
566 | |
567 | /* convert offset to sensor number */ |
568 | idx = *pos >> 2; |
569 | |
570 | valuesize = sizeof(values); |
571 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->read_sensor) |
572 | r = amdgpu_dpm_read_sensor(adev, idx, &values[0], &valuesize); |
573 | else |
574 | return -EINVAL; |
575 | |
576 | if (size > valuesize) |
577 | return -EINVAL; |
578 | |
579 | outsize = 0; |
580 | x = 0; |
581 | if (!r) { |
582 | while (size) { |
583 | r = put_user(values[x++], (int32_t *)buf); |
584 | buf += 4; |
585 | size -= 4; |
586 | outsize += 4; |
587 | } |
588 | } |
589 | |
590 | return !r ? outsize : r; |
591 | } |
592 | |
593 | /** amdgpu_debugfs_wave_read - Read WAVE STATUS data |
594 | * |
595 | * @f: open file handle |
596 | * @buf: User buffer to store read data in |
597 | * @size: Number of bytes to read |
598 | * @pos: Offset to seek to |
599 | * |
600 | * The offset being sought changes which wave that the status data |
601 | * will be returned for. The bits are used as follows: |
602 | * |
603 | * Bits 0..6: Byte offset into data |
604 | * Bits 7..14: SE selector |
605 | * Bits 15..22: SH/SA selector |
606 | * Bits 23..30: CU/{WGP+SIMD} selector |
607 | * Bits 31..36: WAVE ID selector |
608 | * Bits 37..44: SIMD ID selector |
609 | * |
610 | * The returned data begins with one DWORD of version information |
611 | * Followed by WAVE STATUS registers relevant to the GFX IP version |
612 | * being used. See gfx_v8_0_read_wave_data() for an example output. |
613 | */ |
614 | static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, |
615 | size_t size, loff_t *pos) |
616 | { |
617 | struct amdgpu_device *adev = f->f_inode->i_private; |
618 | int r, x; |
619 | ssize_t result=0; |
620 | uint32_t offset, se, sh, cu, wave, simd, data[32]; |
621 | |
622 | if (size & 3 || *pos & 3) |
623 | return -EINVAL; |
624 | |
625 | /* decode offset */ |
626 | offset = (*pos & GENMASK_ULL(6, 0)); |
627 | se = (*pos & GENMASK_ULL(14, 7)) >> 7; |
628 | sh = (*pos & GENMASK_ULL(22, 15)) >> 15; |
629 | cu = (*pos & GENMASK_ULL(30, 23)) >> 23; |
630 | wave = (*pos & GENMASK_ULL(36, 31)) >> 31; |
631 | simd = (*pos & GENMASK_ULL(44, 37)) >> 37; |
632 | |
633 | /* switch to the specific se/sh/cu */ |
634 | mutex_lock(&adev->grbm_idx_mutex); |
635 | amdgpu_gfx_select_se_sh(adev, se, sh, cu); |
636 | |
637 | x = 0; |
638 | if (adev->gfx.funcs->read_wave_data) |
639 | adev->gfx.funcs->read_wave_data(adev, simd, wave, data, &x); |
640 | |
641 | amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); |
642 | mutex_unlock(&adev->grbm_idx_mutex); |
643 | |
644 | if (!x) |
645 | return -EINVAL; |
646 | |
647 | while (size && (offset < x * 4)) { |
648 | uint32_t value; |
649 | |
650 | value = data[offset >> 2]; |
651 | r = put_user(value, (uint32_t *)buf); |
652 | if (r) |
653 | return r; |
654 | |
655 | result += 4; |
656 | buf += 4; |
657 | offset += 4; |
658 | size -= 4; |
659 | } |
660 | |
661 | return result; |
662 | } |
663 | |
664 | /** amdgpu_debugfs_gpr_read - Read wave gprs |
665 | * |
666 | * @f: open file handle |
667 | * @buf: User buffer to store read data in |
668 | * @size: Number of bytes to read |
669 | * @pos: Offset to seek to |
670 | * |
671 | * The offset being sought changes which wave that the status data |
672 | * will be returned for. The bits are used as follows: |
673 | * |
674 | * Bits 0..11: Byte offset into data |
675 | * Bits 12..19: SE selector |
676 | * Bits 20..27: SH/SA selector |
677 | * Bits 28..35: CU/{WGP+SIMD} selector |
678 | * Bits 36..43: WAVE ID selector |
679 | * Bits 37..44: SIMD ID selector |
680 | * Bits 52..59: Thread selector |
681 | * Bits 60..61: Bank selector (VGPR=0,SGPR=1) |
682 | * |
683 | * The return data comes from the SGPR or VGPR register bank for |
684 | * the selected operational unit. |
685 | */ |
686 | static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, |
687 | size_t size, loff_t *pos) |
688 | { |
689 | struct amdgpu_device *adev = f->f_inode->i_private; |
690 | int r; |
691 | ssize_t result = 0; |
692 | uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data; |
693 | |
694 | if (size & 3 || *pos & 3) |
695 | return -EINVAL; |
696 | |
697 | /* decode offset */ |
698 | offset = *pos & GENMASK_ULL(11, 0); |
699 | se = (*pos & GENMASK_ULL(19, 12)) >> 12; |
700 | sh = (*pos & GENMASK_ULL(27, 20)) >> 20; |
701 | cu = (*pos & GENMASK_ULL(35, 28)) >> 28; |
702 | wave = (*pos & GENMASK_ULL(43, 36)) >> 36; |
703 | simd = (*pos & GENMASK_ULL(51, 44)) >> 44; |
704 | thread = (*pos & GENMASK_ULL(59, 52)) >> 52; |
705 | bank = (*pos & GENMASK_ULL(61, 60)) >> 60; |
706 | |
707 | data = kmalloc_array(1024, sizeof(*data), GFP_KERNEL); |
708 | if (!data) |
709 | return -ENOMEM; |
710 | |
711 | /* switch to the specific se/sh/cu */ |
712 | mutex_lock(&adev->grbm_idx_mutex); |
713 | amdgpu_gfx_select_se_sh(adev, se, sh, cu); |
714 | |
715 | if (bank == 0) { |
716 | if (adev->gfx.funcs->read_wave_vgprs) |
717 | adev->gfx.funcs->read_wave_vgprs(adev, simd, wave, thread, offset, size>>2, data); |
718 | } else { |
719 | if (adev->gfx.funcs->read_wave_sgprs) |
720 | adev->gfx.funcs->read_wave_sgprs(adev, simd, wave, offset, size>>2, data); |
721 | } |
722 | |
723 | amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); |
724 | mutex_unlock(&adev->grbm_idx_mutex); |
725 | |
726 | while (size) { |
727 | uint32_t value; |
728 | |
729 | value = data[offset++]; |
730 | r = put_user(value, (uint32_t *)buf); |
731 | if (r) { |
732 | result = r; |
733 | goto err; |
734 | } |
735 | |
736 | result += 4; |
737 | buf += 4; |
738 | size -= 4; |
739 | } |
740 | |
741 | err: |
742 | kfree(data); |
743 | return result; |
744 | } |
745 | |
746 | static const struct file_operations amdgpu_debugfs_regs_fops = { |
747 | .owner = THIS_MODULE, |
748 | .read = amdgpu_debugfs_regs_read, |
749 | .write = amdgpu_debugfs_regs_write, |
750 | .llseek = default_llseek |
751 | }; |
752 | static const struct file_operations amdgpu_debugfs_regs_didt_fops = { |
753 | .owner = THIS_MODULE, |
754 | .read = amdgpu_debugfs_regs_didt_read, |
755 | .write = amdgpu_debugfs_regs_didt_write, |
756 | .llseek = default_llseek |
757 | }; |
758 | static const struct file_operations amdgpu_debugfs_regs_pcie_fops = { |
759 | .owner = THIS_MODULE, |
760 | .read = amdgpu_debugfs_regs_pcie_read, |
761 | .write = amdgpu_debugfs_regs_pcie_write, |
762 | .llseek = default_llseek |
763 | }; |
764 | static const struct file_operations amdgpu_debugfs_regs_smc_fops = { |
765 | .owner = THIS_MODULE, |
766 | .read = amdgpu_debugfs_regs_smc_read, |
767 | .write = amdgpu_debugfs_regs_smc_write, |
768 | .llseek = default_llseek |
769 | }; |
770 | |
771 | static const struct file_operations amdgpu_debugfs_gca_config_fops = { |
772 | .owner = THIS_MODULE, |
773 | .read = amdgpu_debugfs_gca_config_read, |
774 | .llseek = default_llseek |
775 | }; |
776 | |
777 | static const struct file_operations amdgpu_debugfs_sensors_fops = { |
778 | .owner = THIS_MODULE, |
779 | .read = amdgpu_debugfs_sensor_read, |
780 | .llseek = default_llseek |
781 | }; |
782 | |
783 | static const struct file_operations amdgpu_debugfs_wave_fops = { |
784 | .owner = THIS_MODULE, |
785 | .read = amdgpu_debugfs_wave_read, |
786 | .llseek = default_llseek |
787 | }; |
788 | static const struct file_operations amdgpu_debugfs_gpr_fops = { |
789 | .owner = THIS_MODULE, |
790 | .read = amdgpu_debugfs_gpr_read, |
791 | .llseek = default_llseek |
792 | }; |
793 | |
794 | static const struct file_operations *debugfs_regs[] = { |
795 | &amdgpu_debugfs_regs_fops, |
796 | &amdgpu_debugfs_regs_didt_fops, |
797 | &amdgpu_debugfs_regs_pcie_fops, |
798 | &amdgpu_debugfs_regs_smc_fops, |
799 | &amdgpu_debugfs_gca_config_fops, |
800 | &amdgpu_debugfs_sensors_fops, |
801 | &amdgpu_debugfs_wave_fops, |
802 | &amdgpu_debugfs_gpr_fops, |
803 | }; |
804 | |
805 | static const char *debugfs_regs_names[] = { |
806 | "amdgpu_regs" , |
807 | "amdgpu_regs_didt" , |
808 | "amdgpu_regs_pcie" , |
809 | "amdgpu_regs_smc" , |
810 | "amdgpu_gca_config" , |
811 | "amdgpu_sensors" , |
812 | "amdgpu_wave" , |
813 | "amdgpu_gpr" , |
814 | }; |
815 | |
816 | /** |
817 | * amdgpu_debugfs_regs_init - Initialize debugfs entries that provide |
818 | * register access. |
819 | * |
820 | * @adev: The device to attach the debugfs entries to |
821 | */ |
822 | int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) |
823 | { |
824 | struct drm_minor *minor = adev->ddev->primary; |
825 | struct dentry *ent, *root = minor->debugfs_root; |
826 | unsigned int i; |
827 | |
828 | for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) { |
829 | ent = debugfs_create_file(debugfs_regs_names[i], |
830 | S_IFREG | S_IRUGO, root, |
831 | adev, debugfs_regs[i]); |
832 | if (!i && !IS_ERR_OR_NULL(ent)) |
833 | i_size_write(ent->d_inode, adev->rmmio_size); |
834 | adev->debugfs_regs[i] = ent; |
835 | } |
836 | |
837 | return 0; |
838 | } |
839 | |
840 | void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev) |
841 | { |
842 | unsigned i; |
843 | |
844 | for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) { |
845 | if (adev->debugfs_regs[i]) { |
846 | debugfs_remove(adev->debugfs_regs[i]); |
847 | adev->debugfs_regs[i] = NULL; |
848 | } |
849 | } |
850 | } |
851 | |
852 | static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) |
853 | { |
854 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
855 | struct drm_device *dev = node->minor->dev; |
856 | struct amdgpu_device *adev = dev->dev_private; |
857 | int r = 0, i; |
858 | |
859 | /* hold on the scheduler */ |
860 | for (i = 0; i < AMDGPU_MAX_RINGS; i++) { |
861 | struct amdgpu_ring *ring = adev->rings[i]; |
862 | |
863 | if (!ring || !ring->sched.thread) |
864 | continue; |
865 | kthread_park(ring->sched.thread); |
866 | } |
867 | |
868 | seq_printf(m, "run ib test:\n" ); |
869 | r = amdgpu_ib_ring_tests(adev); |
870 | if (r) |
871 | seq_printf(m, "ib ring tests failed (%d).\n" , r); |
872 | else |
873 | seq_printf(m, "ib ring tests passed.\n" ); |
874 | |
875 | /* go on the scheduler */ |
876 | for (i = 0; i < AMDGPU_MAX_RINGS; i++) { |
877 | struct amdgpu_ring *ring = adev->rings[i]; |
878 | |
879 | if (!ring || !ring->sched.thread) |
880 | continue; |
881 | kthread_unpark(ring->sched.thread); |
882 | } |
883 | |
884 | return 0; |
885 | } |
886 | |
887 | static int amdgpu_debugfs_get_vbios_dump(struct seq_file *m, void *data) |
888 | { |
889 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
890 | struct drm_device *dev = node->minor->dev; |
891 | struct amdgpu_device *adev = dev->dev_private; |
892 | |
893 | seq_write(m, adev->bios, adev->bios_size); |
894 | return 0; |
895 | } |
896 | |
897 | static int amdgpu_debugfs_evict_vram(struct seq_file *m, void *data) |
898 | { |
899 | struct drm_info_node *node = (struct drm_info_node *)m->private; |
900 | struct drm_device *dev = node->minor->dev; |
901 | struct amdgpu_device *adev = dev->dev_private; |
902 | |
903 | seq_printf(m, "(%d)\n" , amdgpu_bo_evict_vram(adev)); |
904 | return 0; |
905 | } |
906 | |
907 | static int amdgpu_debugfs_evict_gtt(struct seq_file *m, void *data) |
908 | { |
909 | struct drm_info_node *node = (struct drm_info_node *)m->private; |
910 | struct drm_device *dev = node->minor->dev; |
911 | struct amdgpu_device *adev = dev->dev_private; |
912 | |
913 | seq_printf(m, "(%d)\n" , ttm_bo_evict_mm(&adev->mman.bdev, TTM_PL_TT)); |
914 | return 0; |
915 | } |
916 | |
917 | static const struct drm_info_list amdgpu_debugfs_list[] = { |
918 | {"amdgpu_vbios" , amdgpu_debugfs_get_vbios_dump}, |
919 | {"amdgpu_test_ib" , &amdgpu_debugfs_test_ib}, |
920 | {"amdgpu_evict_vram" , &amdgpu_debugfs_evict_vram}, |
921 | {"amdgpu_evict_gtt" , &amdgpu_debugfs_evict_gtt}, |
922 | }; |
923 | |
924 | int amdgpu_debugfs_init(struct amdgpu_device *adev) |
925 | { |
926 | return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_list, |
927 | ARRAY_SIZE(amdgpu_debugfs_list)); |
928 | } |
929 | |
930 | #else |
931 | int amdgpu_debugfs_init(struct amdgpu_device *adev) |
932 | { |
933 | return 0; |
934 | } |
935 | int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) |
936 | { |
937 | return 0; |
938 | } |
939 | void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev) { } |
940 | #endif |
941 | |