a5xx_debugfs.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
  3. */
  4. #include <linux/types.h>
  5. #include <linux/debugfs.h>
  6. #include <drm/drm_debugfs.h>
  7. #include <drm/drm_file.h>
  8. #include <drm/drm_print.h>
  9. #include "a5xx_gpu.h"
  10. static void pfp_print(struct msm_gpu *gpu, struct drm_printer *p)
  11. {
  12. int i;
  13. drm_printf(p, "PFP state:\n");
  14. for (i = 0; i < 36; i++) {
  15. gpu_write(gpu, REG_A5XX_CP_PFP_STAT_ADDR, i);
  16. drm_printf(p, " %02x: %08x\n", i,
  17. gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA));
  18. }
  19. }
  20. static void me_print(struct msm_gpu *gpu, struct drm_printer *p)
  21. {
  22. int i;
  23. drm_printf(p, "ME state:\n");
  24. for (i = 0; i < 29; i++) {
  25. gpu_write(gpu, REG_A5XX_CP_ME_STAT_ADDR, i);
  26. drm_printf(p, " %02x: %08x\n", i,
  27. gpu_read(gpu, REG_A5XX_CP_ME_STAT_DATA));
  28. }
  29. }
  30. static void meq_print(struct msm_gpu *gpu, struct drm_printer *p)
  31. {
  32. int i;
  33. drm_printf(p, "MEQ state:\n");
  34. gpu_write(gpu, REG_A5XX_CP_MEQ_DBG_ADDR, 0);
  35. for (i = 0; i < 64; i++) {
  36. drm_printf(p, " %02x: %08x\n", i,
  37. gpu_read(gpu, REG_A5XX_CP_MEQ_DBG_DATA));
  38. }
  39. }
  40. static void roq_print(struct msm_gpu *gpu, struct drm_printer *p)
  41. {
  42. int i;
  43. drm_printf(p, "ROQ state:\n");
  44. gpu_write(gpu, REG_A5XX_CP_ROQ_DBG_ADDR, 0);
  45. for (i = 0; i < 512 / 4; i++) {
  46. uint32_t val[4];
  47. int j;
  48. for (j = 0; j < 4; j++)
  49. val[j] = gpu_read(gpu, REG_A5XX_CP_ROQ_DBG_DATA);
  50. drm_printf(p, " %02x: %08x %08x %08x %08x\n", i,
  51. val[0], val[1], val[2], val[3]);
  52. }
  53. }
  54. static int show(struct seq_file *m, void *arg)
  55. {
  56. struct drm_info_node *node = m->private;
  57. struct drm_device *dev = node->minor->dev;
  58. struct msm_drm_private *priv = dev->dev_private;
  59. struct drm_printer p = drm_seq_file_printer(m);
  60. void (*show)(struct msm_gpu *gpu, struct drm_printer *p) =
  61. node->info_ent->data;
  62. show(priv->gpu, &p);
  63. return 0;
  64. }
  65. #define ENT(n) { .name = #n, .show = show, .data = n ##_print }
  66. static struct drm_info_list a5xx_debugfs_list[] = {
  67. ENT(pfp),
  68. ENT(me),
  69. ENT(meq),
  70. ENT(roq),
  71. };
  72. /* for debugfs files that can be written to, we can't use drm helper: */
  73. static int
  74. reset_set(void *data, u64 val)
  75. {
  76. struct drm_device *dev = data;
  77. struct msm_drm_private *priv = dev->dev_private;
  78. struct msm_gpu *gpu = priv->gpu;
  79. struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
  80. struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
  81. if (!capable(CAP_SYS_ADMIN))
  82. return -EINVAL;
  83. /* TODO do we care about trying to make sure the GPU is idle?
  84. * Since this is just a debug feature limited to CAP_SYS_ADMIN,
  85. * maybe it is fine to let the user keep both pieces if they
  86. * try to reset an active GPU.
  87. */
  88. mutex_lock(&gpu->lock);
  89. release_firmware(adreno_gpu->fw[ADRENO_FW_PM4]);
  90. adreno_gpu->fw[ADRENO_FW_PM4] = NULL;
  91. release_firmware(adreno_gpu->fw[ADRENO_FW_PFP]);
  92. adreno_gpu->fw[ADRENO_FW_PFP] = NULL;
  93. if (a5xx_gpu->pm4_bo) {
  94. msm_gem_unpin_iova(a5xx_gpu->pm4_bo, gpu->vm);
  95. drm_gem_object_put(a5xx_gpu->pm4_bo);
  96. a5xx_gpu->pm4_bo = NULL;
  97. }
  98. if (a5xx_gpu->pfp_bo) {
  99. msm_gem_unpin_iova(a5xx_gpu->pfp_bo, gpu->vm);
  100. drm_gem_object_put(a5xx_gpu->pfp_bo);
  101. a5xx_gpu->pfp_bo = NULL;
  102. }
  103. gpu->needs_hw_init = true;
  104. pm_runtime_get_sync(&gpu->pdev->dev);
  105. gpu->funcs->recover(gpu);
  106. pm_runtime_put_sync(&gpu->pdev->dev);
  107. mutex_unlock(&gpu->lock);
  108. return 0;
  109. }
  110. DEFINE_DEBUGFS_ATTRIBUTE(reset_fops, NULL, reset_set, "%llx\n");
  111. void a5xx_debugfs_init(struct msm_gpu *gpu, struct drm_minor *minor)
  112. {
  113. struct drm_device *dev;
  114. if (!minor)
  115. return;
  116. dev = minor->dev;
  117. drm_debugfs_create_files(a5xx_debugfs_list,
  118. ARRAY_SIZE(a5xx_debugfs_list),
  119. minor->debugfs_root, minor);
  120. debugfs_create_file_unsafe("reset", S_IWUGO, minor->debugfs_root, dev,
  121. &reset_fops);
  122. }