diff options
author | Tom St Denis <tom.stdenis@amd.com> | 2016-04-27 12:41:16 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-07-07 14:51:10 -0400 |
commit | 4f4824b55650fa7014eedf18cb1f9f243cb2b45e (patch) | |
tree | 1c415d1fed66a37574b1f677fadd038cbd2af51f /drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | |
parent | 8491999285a3e5a5395ac87098bb1f26c465b62b (diff) |
drm/amd/amdgpu: Convert ring debugfs entries to binary
They now emit ring data in binary which will be read/written by
the userspace tool umr shortly.
Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 127 |
1 files changed, 62 insertions, 65 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index dc8a7bbedfea..5491696ac827 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | |||
@@ -28,6 +28,7 @@ | |||
28 | */ | 28 | */ |
29 | #include <linux/seq_file.h> | 29 | #include <linux/seq_file.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/debugfs.h> | ||
31 | #include <drm/drmP.h> | 32 | #include <drm/drmP.h> |
32 | #include <drm/amdgpu_drm.h> | 33 | #include <drm/amdgpu_drm.h> |
33 | #include "amdgpu.h" | 34 | #include "amdgpu.h" |
@@ -368,57 +369,62 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring) | |||
368 | */ | 369 | */ |
369 | #if defined(CONFIG_DEBUG_FS) | 370 | #if defined(CONFIG_DEBUG_FS) |
370 | 371 | ||
371 | static int amdgpu_debugfs_ring_info(struct seq_file *m, void *data) | 372 | /* Layout of file is 12 bytes consisting of |
373 | * - rptr | ||
374 | * - wptr | ||
375 | * - driver's copy of wptr | ||
376 | * | ||
377 | * followed by n-words of ring data | ||
378 | */ | ||
379 | static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf, | ||
380 | size_t size, loff_t *pos) | ||
372 | { | 381 | { |
373 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 382 | struct amdgpu_ring *ring = (struct amdgpu_ring*)f->f_inode->i_private; |
374 | struct drm_device *dev = node->minor->dev; | 383 | int r, i; |
375 | struct amdgpu_device *adev = dev->dev_private; | 384 | uint32_t value, result, early[3]; |
376 | int roffset = (unsigned long)node->info_ent->data; | 385 | |
377 | struct amdgpu_ring *ring = (void *)(((uint8_t*)adev) + roffset); | 386 | if (*pos & 3) |
378 | uint32_t rptr, wptr, rptr_next; | 387 | return -EINVAL; |
379 | unsigned i; | 388 | |
380 | 389 | result = 0; | |
381 | wptr = amdgpu_ring_get_wptr(ring); | 390 | |
382 | seq_printf(m, "wptr: 0x%08x [%5d]\n", wptr, wptr); | 391 | if (*pos < 12) { |
383 | 392 | early[0] = amdgpu_ring_get_rptr(ring); | |
384 | rptr = amdgpu_ring_get_rptr(ring); | 393 | early[1] = amdgpu_ring_get_wptr(ring); |
385 | rptr_next = le32_to_cpu(*ring->next_rptr_cpu_addr); | 394 | early[2] = ring->wptr; |
386 | 395 | for (i = *pos / 4; i < 3 && size; i++) { | |
387 | seq_printf(m, "rptr: 0x%08x [%5d]\n", rptr, rptr); | 396 | r = put_user(early[i], (uint32_t *)buf); |
388 | 397 | if (r) | |
389 | seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", | 398 | return r; |
390 | ring->wptr, ring->wptr); | 399 | buf += 4; |
391 | 400 | result += 4; | |
392 | if (!ring->ready) | 401 | size -= 4; |
393 | return 0; | 402 | *pos += 4; |
394 | 403 | } | |
395 | /* print 8 dw before current rptr as often it's the last executed | ||
396 | * packet that is the root issue | ||
397 | */ | ||
398 | i = (rptr + ring->ptr_mask + 1 - 32) & ring->ptr_mask; | ||
399 | while (i != rptr) { | ||
400 | seq_printf(m, "r[%5d]=0x%08x", i, ring->ring[i]); | ||
401 | if (i == rptr) | ||
402 | seq_puts(m, " *"); | ||
403 | if (i == rptr_next) | ||
404 | seq_puts(m, " #"); | ||
405 | seq_puts(m, "\n"); | ||
406 | i = (i + 1) & ring->ptr_mask; | ||
407 | } | 404 | } |
408 | while (i != wptr) { | 405 | |
409 | seq_printf(m, "r[%5d]=0x%08x", i, ring->ring[i]); | 406 | while (size) { |
410 | if (i == rptr) | 407 | if (*pos >= (ring->ring_size + 12)) |
411 | seq_puts(m, " *"); | 408 | return result; |
412 | if (i == rptr_next) | 409 | |
413 | seq_puts(m, " #"); | 410 | value = ring->ring[(*pos - 12)/4]; |
414 | seq_puts(m, "\n"); | 411 | r = put_user(value, (uint32_t*)buf); |
415 | i = (i + 1) & ring->ptr_mask; | 412 | if (r) |
413 | return r; | ||
414 | buf += 4; | ||
415 | result += 4; | ||
416 | size -= 4; | ||
417 | *pos += 4; | ||
416 | } | 418 | } |
417 | return 0; | 419 | |
420 | return result; | ||
418 | } | 421 | } |
419 | 422 | ||
420 | static struct drm_info_list amdgpu_debugfs_ring_info_list[AMDGPU_MAX_RINGS]; | 423 | static const struct file_operations amdgpu_debugfs_ring_fops = { |
421 | static char amdgpu_debugfs_ring_names[AMDGPU_MAX_RINGS][32]; | 424 | .owner = THIS_MODULE, |
425 | .read = amdgpu_debugfs_ring_read, | ||
426 | .llseek = default_llseek | ||
427 | }; | ||
422 | 428 | ||
423 | #endif | 429 | #endif |
424 | 430 | ||
@@ -426,28 +432,19 @@ static int amdgpu_debugfs_ring_init(struct amdgpu_device *adev, | |||
426 | struct amdgpu_ring *ring) | 432 | struct amdgpu_ring *ring) |
427 | { | 433 | { |
428 | #if defined(CONFIG_DEBUG_FS) | 434 | #if defined(CONFIG_DEBUG_FS) |
429 | unsigned offset = (uint8_t*)ring - (uint8_t*)adev; | 435 | struct drm_minor *minor = adev->ddev->primary; |
430 | unsigned i; | 436 | struct dentry *ent, *root = minor->debugfs_root; |
431 | struct drm_info_list *info; | 437 | char name[32]; |
432 | char *name; | ||
433 | |||
434 | for (i = 0; i < ARRAY_SIZE(amdgpu_debugfs_ring_info_list); ++i) { | ||
435 | info = &amdgpu_debugfs_ring_info_list[i]; | ||
436 | if (!info->data) | ||
437 | break; | ||
438 | } | ||
439 | 438 | ||
440 | if (i == ARRAY_SIZE(amdgpu_debugfs_ring_info_list)) | ||
441 | return -ENOSPC; | ||
442 | |||
443 | name = &amdgpu_debugfs_ring_names[i][0]; | ||
444 | sprintf(name, "amdgpu_ring_%s", ring->name); | 439 | sprintf(name, "amdgpu_ring_%s", ring->name); |
445 | info->name = name; | ||
446 | info->show = amdgpu_debugfs_ring_info; | ||
447 | info->driver_features = 0; | ||
448 | info->data = (void*)(uintptr_t)offset; | ||
449 | 440 | ||
450 | return amdgpu_debugfs_add_files(adev, info, 1); | 441 | ent = debugfs_create_file(name, |
442 | S_IFREG | S_IRUGO, root, | ||
443 | ring, &amdgpu_debugfs_ring_fops); | ||
444 | if (IS_ERR(ent)) | ||
445 | return PTR_ERR(ent); | ||
446 | |||
447 | i_size_write(ent->d_inode, ring->ring_size + 12); | ||
451 | #endif | 448 | #endif |
452 | return 0; | 449 | return 0; |
453 | } | 450 | } |