a5xx_debugfs.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. #include <linux/types.h>
  14. #include <linux/debugfs.h>
  15. #include <drm/drm_print.h>
  16. #include "a5xx_gpu.h"
  17. static int pfp_print(struct msm_gpu *gpu, struct drm_printer *p)
  18. {
  19. int i;
  20. drm_printf(p, "PFP state:\n");
  21. for (i = 0; i < 36; i++) {
  22. gpu_write(gpu, REG_A5XX_CP_PFP_STAT_ADDR, i);
  23. drm_printf(p, " %02x: %08x\n", i,
  24. gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA));
  25. }
  26. return 0;
  27. }
  28. static int me_print(struct msm_gpu *gpu, struct drm_printer *p)
  29. {
  30. int i;
  31. drm_printf(p, "ME state:\n");
  32. for (i = 0; i < 29; i++) {
  33. gpu_write(gpu, REG_A5XX_CP_ME_STAT_ADDR, i);
  34. drm_printf(p, " %02x: %08x\n", i,
  35. gpu_read(gpu, REG_A5XX_CP_ME_STAT_DATA));
  36. }
  37. return 0;
  38. }
  39. static int meq_print(struct msm_gpu *gpu, struct drm_printer *p)
  40. {
  41. int i;
  42. drm_printf(p, "MEQ state:\n");
  43. gpu_write(gpu, REG_A5XX_CP_MEQ_DBG_ADDR, 0);
  44. for (i = 0; i < 64; i++) {
  45. drm_printf(p, " %02x: %08x\n", i,
  46. gpu_read(gpu, REG_A5XX_CP_MEQ_DBG_DATA));
  47. }
  48. return 0;
  49. }
  50. static int roq_print(struct msm_gpu *gpu, struct drm_printer *p)
  51. {
  52. int i;
  53. drm_printf(p, "ROQ state:\n");
  54. gpu_write(gpu, REG_A5XX_CP_ROQ_DBG_ADDR, 0);
  55. for (i = 0; i < 512 / 4; i++) {
  56. uint32_t val[4];
  57. int j;
  58. for (j = 0; j < 4; j++)
  59. val[j] = gpu_read(gpu, REG_A5XX_CP_ROQ_DBG_DATA);
  60. drm_printf(p, " %02x: %08x %08x %08x %08x\n", i,
  61. val[0], val[1], val[2], val[3]);
  62. }
  63. return 0;
  64. }
  65. static int show(struct seq_file *m, void *arg)
  66. {
  67. struct drm_info_node *node = (struct drm_info_node *) m->private;
  68. struct drm_device *dev = node->minor->dev;
  69. struct msm_drm_private *priv = dev->dev_private;
  70. struct drm_printer p = drm_seq_file_printer(m);
  71. int (*show)(struct msm_gpu *gpu, struct drm_printer *p) =
  72. node->info_ent->data;
  73. return show(priv->gpu, &p);
  74. }
  75. #define ENT(n) { .name = #n, .show = show, .data = n ##_print }
  76. static struct drm_info_list a5xx_debugfs_list[] = {
  77. ENT(pfp),
  78. ENT(me),
  79. ENT(meq),
  80. ENT(roq),
  81. };
  82. /* for debugfs files that can be written to, we can't use drm helper: */
  83. static int
  84. reset_set(void *data, u64 val)
  85. {
  86. struct drm_device *dev = data;
  87. struct msm_drm_private *priv = dev->dev_private;
  88. struct msm_gpu *gpu = priv->gpu;
  89. struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
  90. struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
  91. if (!capable(CAP_SYS_ADMIN))
  92. return -EINVAL;
  93. /* TODO do we care about trying to make sure the GPU is idle?
  94. * Since this is just a debug feature limited to CAP_SYS_ADMIN,
  95. * maybe it is fine to let the user keep both pieces if they
  96. * try to reset an active GPU.
  97. */
  98. mutex_lock(&dev->struct_mutex);
  99. release_firmware(adreno_gpu->fw[ADRENO_FW_PM4]);
  100. adreno_gpu->fw[ADRENO_FW_PM4] = NULL;
  101. release_firmware(adreno_gpu->fw[ADRENO_FW_PFP]);
  102. adreno_gpu->fw[ADRENO_FW_PFP] = NULL;
  103. if (a5xx_gpu->pm4_bo) {
  104. if (a5xx_gpu->pm4_iova)
  105. msm_gem_put_iova(a5xx_gpu->pm4_bo, gpu->aspace);
  106. drm_gem_object_put(a5xx_gpu->pm4_bo);
  107. a5xx_gpu->pm4_bo = NULL;
  108. }
  109. if (a5xx_gpu->pfp_bo) {
  110. if (a5xx_gpu->pfp_iova)
  111. msm_gem_put_iova(a5xx_gpu->pfp_bo, gpu->aspace);
  112. drm_gem_object_put(a5xx_gpu->pfp_bo);
  113. a5xx_gpu->pfp_bo = NULL;
  114. }
  115. gpu->needs_hw_init = true;
  116. pm_runtime_get_sync(&gpu->pdev->dev);
  117. gpu->funcs->recover(gpu);
  118. pm_runtime_put_sync(&gpu->pdev->dev);
  119. mutex_unlock(&dev->struct_mutex);
  120. return 0;
  121. }
  122. DEFINE_SIMPLE_ATTRIBUTE(reset_fops, NULL, reset_set, "%llx\n");
  123. int a5xx_debugfs_init(struct msm_gpu *gpu, struct drm_minor *minor)
  124. {
  125. struct drm_device *dev;
  126. struct dentry *ent;
  127. int ret;
  128. if (!minor)
  129. return 0;
  130. dev = minor->dev;
  131. ret = drm_debugfs_create_files(a5xx_debugfs_list,
  132. ARRAY_SIZE(a5xx_debugfs_list),
  133. minor->debugfs_root, minor);
  134. if (ret) {
  135. dev_err(dev->dev, "could not install a5xx_debugfs_list\n");
  136. return ret;
  137. }
  138. ent = debugfs_create_file("reset", S_IWUGO,
  139. minor->debugfs_root,
  140. dev, &reset_fops);
  141. if (!ent)
  142. return -ENOMEM;
  143. return 0;
  144. }