adreno_gen7_gmu_snapshot.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include "gen7_reg.h"
  7. #include "adreno.h"
  8. #include "adreno_gen7.h"
  9. #include "adreno_gen7_gmu.h"
  10. #include "adreno_snapshot.h"
  11. #include "adreno_gen7_0_0_snapshot.h"
  12. #include "adreno_gen7_2_0_snapshot.h"
  13. #include "kgsl_device.h"
  14. size_t gen7_snapshot_gmu_mem(struct kgsl_device *device,
  15. u8 *buf, size_t remain, void *priv)
  16. {
  17. struct kgsl_snapshot_gmu_mem *mem_hdr =
  18. (struct kgsl_snapshot_gmu_mem *)buf;
  19. unsigned int *data = (unsigned int *)
  20. (buf + sizeof(*mem_hdr));
  21. struct gmu_mem_type_desc *desc = priv;
  22. if (priv == NULL || desc->memdesc->hostptr == NULL)
  23. return 0;
  24. if (remain < desc->memdesc->size + sizeof(*mem_hdr)) {
  25. dev_err(device->dev,
  26. "snapshot: Not enough memory for the gmu section %d\n",
  27. desc->type);
  28. return 0;
  29. }
  30. mem_hdr->type = desc->type;
  31. mem_hdr->hostaddr = (u64)(uintptr_t)desc->memdesc->hostptr;
  32. mem_hdr->gmuaddr = desc->memdesc->gmuaddr;
  33. mem_hdr->gpuaddr = 0;
  34. /* The hw fence queues are mapped as iomem in the kernel */
  35. if (desc->type == SNAPSHOT_GMU_MEM_HW_FENCE)
  36. memcpy_fromio(data, desc->memdesc->hostptr, desc->memdesc->size);
  37. else
  38. memcpy(data, desc->memdesc->hostptr, desc->memdesc->size);
  39. return desc->memdesc->size + sizeof(*mem_hdr);
  40. }
  41. static size_t gen7_gmu_snapshot_dtcm(struct kgsl_device *device,
  42. u8 *buf, size_t remain, void *priv)
  43. {
  44. struct kgsl_snapshot_gmu_mem *mem_hdr =
  45. (struct kgsl_snapshot_gmu_mem *)buf;
  46. struct gen7_gmu_device *gmu = (struct gen7_gmu_device *)priv;
  47. struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
  48. u32 *data = (u32 *)(buf + sizeof(*mem_hdr));
  49. u32 i;
  50. if (remain < gmu->vma[GMU_DTCM].size + sizeof(*mem_hdr)) {
  51. SNAPSHOT_ERR_NOMEM(device, "GMU DTCM Memory");
  52. return 0;
  53. }
  54. mem_hdr->type = SNAPSHOT_GMU_MEM_BIN_BLOCK;
  55. mem_hdr->hostaddr = 0;
  56. mem_hdr->gmuaddr = gmu->vma[GMU_DTCM].start;
  57. mem_hdr->gpuaddr = 0;
  58. /*
  59. * Read of GMU TCMs over side-band debug controller interface is
  60. * supported on gen7_2_x family
  61. */
  62. if (adreno_is_gen7_2_x_family(adreno_dev)) {
  63. /*
  64. * region [20]: Dump ITCM/DTCM. Select 1 for DTCM.
  65. * autoInc [31]: Autoincrement the address field after each
  66. * access to TCM_DBG_DATA
  67. */
  68. kgsl_regwrite(device, GEN7_CX_DBGC_TCM_DBG_ADDR, BIT(20) | BIT(31));
  69. for (i = 0; i < (gmu->vma[GMU_DTCM].size >> 2); i++)
  70. kgsl_regread(device, GEN7_CX_DBGC_TCM_DBG_DATA, data++);
  71. } else {
  72. for (i = 0; i < (gmu->vma[GMU_DTCM].size >> 2); i++)
  73. gmu_core_regread(device, GEN7_GMU_CM3_DTCM_START + i, data++);
  74. }
  75. return gmu->vma[GMU_DTCM].size + sizeof(*mem_hdr);
  76. }
  77. static size_t gen7_gmu_snapshot_itcm(struct kgsl_device *device,
  78. u8 *buf, size_t remain, void *priv)
  79. {
  80. struct kgsl_snapshot_gmu_mem *mem_hdr =
  81. (struct kgsl_snapshot_gmu_mem *)buf;
  82. void *dest = buf + sizeof(*mem_hdr);
  83. struct gen7_gmu_device *gmu = (struct gen7_gmu_device *)priv;
  84. if (!gmu->itcm_shadow) {
  85. dev_err(&gmu->pdev->dev, "No memory allocated for ITCM shadow capture\n");
  86. return 0;
  87. }
  88. if (remain < gmu->vma[GMU_ITCM].size + sizeof(*mem_hdr)) {
  89. SNAPSHOT_ERR_NOMEM(device, "GMU ITCM Memory");
  90. return 0;
  91. }
  92. mem_hdr->type = SNAPSHOT_GMU_MEM_BIN_BLOCK;
  93. mem_hdr->hostaddr = 0;
  94. mem_hdr->gmuaddr = gmu->vma[GMU_ITCM].start;
  95. mem_hdr->gpuaddr = 0;
  96. memcpy(dest, gmu->itcm_shadow, gmu->vma[GMU_ITCM].size);
  97. return gmu->vma[GMU_ITCM].size + sizeof(*mem_hdr);
  98. }
  99. static void gen7_gmu_snapshot_memories(struct kgsl_device *device,
  100. struct gen7_gmu_device *gmu, struct kgsl_snapshot *snapshot)
  101. {
  102. struct gmu_mem_type_desc desc;
  103. struct kgsl_memdesc *md;
  104. int i;
  105. for (i = 0; i < ARRAY_SIZE(gmu->gmu_globals); i++) {
  106. md = &gmu->gmu_globals[i];
  107. if (!md->size)
  108. continue;
  109. desc.memdesc = md;
  110. if (md == gmu->hfi.hfi_mem)
  111. desc.type = SNAPSHOT_GMU_MEM_HFI;
  112. else if (md == gmu->gmu_log)
  113. desc.type = SNAPSHOT_GMU_MEM_LOG;
  114. else if (md == gmu->dump_mem)
  115. desc.type = SNAPSHOT_GMU_MEM_DEBUG;
  116. else if ((md == gmu->gmu_init_scratch) || (md == gmu->gpu_boot_scratch))
  117. desc.type = SNAPSHOT_GMU_MEM_WARMBOOT;
  118. else if (md == gmu->vrb)
  119. desc.type = SNAPSHOT_GMU_MEM_VRB;
  120. else if (md == gmu->trace.md)
  121. desc.type = SNAPSHOT_GMU_MEM_TRACE;
  122. else
  123. desc.type = SNAPSHOT_GMU_MEM_BIN_BLOCK;
  124. kgsl_snapshot_add_section(device,
  125. KGSL_SNAPSHOT_SECTION_GMU_MEMORY,
  126. snapshot, gen7_snapshot_gmu_mem, &desc);
  127. }
  128. }
  129. struct kgsl_snapshot_gmu_version {
  130. u32 type;
  131. u32 value;
  132. };
  133. static size_t gen7_snapshot_gmu_version(struct kgsl_device *device,
  134. u8 *buf, size_t remain, void *priv)
  135. {
  136. struct kgsl_snapshot_debug *header = (struct kgsl_snapshot_debug *)buf;
  137. u32 *data = (u32 *) (buf + sizeof(*header));
  138. struct kgsl_snapshot_gmu_version *ver = priv;
  139. if (remain < DEBUG_SECTION_SZ(1)) {
  140. SNAPSHOT_ERR_NOMEM(device, "GMU Version");
  141. return 0;
  142. }
  143. header->type = ver->type;
  144. header->size = 1;
  145. *data = ver->value;
  146. return DEBUG_SECTION_SZ(1);
  147. }
  148. static void gen7_gmu_snapshot_versions(struct kgsl_device *device,
  149. struct gen7_gmu_device *gmu,
  150. struct kgsl_snapshot *snapshot)
  151. {
  152. int i;
  153. struct kgsl_snapshot_gmu_version gmu_vers[] = {
  154. { .type = SNAPSHOT_DEBUG_GMU_CORE_VERSION,
  155. .value = gmu->ver.core, },
  156. { .type = SNAPSHOT_DEBUG_GMU_CORE_DEV_VERSION,
  157. .value = gmu->ver.core_dev, },
  158. { .type = SNAPSHOT_DEBUG_GMU_PWR_VERSION,
  159. .value = gmu->ver.pwr, },
  160. { .type = SNAPSHOT_DEBUG_GMU_PWR_DEV_VERSION,
  161. .value = gmu->ver.pwr_dev, },
  162. { .type = SNAPSHOT_DEBUG_GMU_HFI_VERSION,
  163. .value = gmu->ver.hfi, },
  164. };
  165. for (i = 0; i < ARRAY_SIZE(gmu_vers); i++)
  166. kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_DEBUG,
  167. snapshot, gen7_snapshot_gmu_version,
  168. &gmu_vers[i]);
  169. }
  170. #define RSCC_OFFSET_DWORDS 0x14000
  171. static size_t gen7_snapshot_rscc_registers(struct kgsl_device *device, u8 *buf,
  172. size_t remain, void *priv)
  173. {
  174. const u32 *regs = priv;
  175. unsigned int *data = (unsigned int *)buf;
  176. int count = 0, k;
  177. struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
  178. struct gen7_gmu_device *gmu = to_gen7_gmu(adreno_dev);
  179. /* Figure out how many registers we are going to dump */
  180. count = adreno_snapshot_regs_count(regs);
  181. if (remain < (count * 4)) {
  182. SNAPSHOT_ERR_NOMEM(device, "RSCC REGISTERS");
  183. return 0;
  184. }
  185. for (regs = priv; regs[0] != UINT_MAX; regs += 2) {
  186. unsigned int cnt = REG_COUNT(regs);
  187. if (cnt == 1) {
  188. *data++ = BIT(31) | regs[0];
  189. *data++ = __raw_readl(gmu->rscc_virt +
  190. ((regs[0] - RSCC_OFFSET_DWORDS) << 2));
  191. continue;
  192. }
  193. *data++ = regs[0];
  194. *data++ = cnt;
  195. for (k = regs[0]; k <= regs[1]; k++)
  196. *data++ = __raw_readl(gmu->rscc_virt +
  197. ((k - RSCC_OFFSET_DWORDS) << 2));
  198. }
  199. /* Return the size of the section */
  200. return (count * 4);
  201. }
  202. /*
  203. * gen7_gmu_device_snapshot() - GEN7 GMU snapshot function
  204. * @device: Device being snapshotted
  205. * @snapshot: Pointer to the snapshot instance
  206. *
  207. * This is where all of the GEN7 GMU specific bits and pieces are grabbed
  208. * into the snapshot memory
  209. */
  210. static void gen7_gmu_device_snapshot(struct kgsl_device *device,
  211. struct kgsl_snapshot *snapshot)
  212. {
  213. struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
  214. struct gen7_gmu_device *gmu = to_gen7_gmu(adreno_dev);
  215. const struct adreno_gen7_core *gpucore = to_gen7_core(ADRENO_DEVICE(device));
  216. const struct gen7_snapshot_block_list *gen7_snapshot_block_list =
  217. gpucore->gen7_snapshot_block_list;
  218. kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GMU_MEMORY,
  219. snapshot, gen7_gmu_snapshot_itcm, gmu);
  220. gen7_gmu_snapshot_versions(device, gmu, snapshot);
  221. gen7_gmu_snapshot_memories(device, gmu, snapshot);
  222. kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS_V2, snapshot,
  223. adreno_snapshot_registers_v2, (void *) gen7_snapshot_block_list->gmu_regs);
  224. kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS_V2, snapshot,
  225. gen7_snapshot_rscc_registers, (void *) gen7_snapshot_block_list->rscc_regs);
  226. if (!gen7_gmu_gx_is_on(adreno_dev))
  227. goto dtcm;
  228. /* Set fence to ALLOW mode so registers can be read */
  229. kgsl_regwrite(device, GEN7_GMU_AO_AHB_FENCE_CTRL, 0);
  230. /* Make sure the previous write posted before reading */
  231. wmb();
  232. kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS_V2, snapshot,
  233. adreno_snapshot_registers_v2, (void *) gen7_snapshot_block_list->gmu_gx_regs);
  234. /*
  235. * A stalled SMMU can lead to NoC timeouts when host accesses DTCM.
  236. * DTCM can be read through side-band DBGC interface on gen7_2_x family.
  237. */
  238. if (adreno_smmu_is_stalled(adreno_dev) && !adreno_is_gen7_2_x_family(adreno_dev)) {
  239. dev_err(&gmu->pdev->dev,
  240. "Not dumping dtcm because SMMU is stalled\n");
  241. return;
  242. }
  243. dtcm:
  244. kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GMU_MEMORY,
  245. snapshot, gen7_gmu_snapshot_dtcm, gmu);
  246. }
  247. void gen7_gmu_snapshot(struct adreno_device *adreno_dev,
  248. struct kgsl_snapshot *snapshot)
  249. {
  250. struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
  251. /*
  252. * Dump external register first to have GPUCC and other external
  253. * register in snapshot to analyze the system state even in partial
  254. * snapshot dump
  255. */
  256. gen7_snapshot_external_core_regs(device, snapshot);
  257. gen7_gmu_device_snapshot(device, snapshot);
  258. gen7_snapshot(adreno_dev, snapshot);
  259. gmu_core_regwrite(device, GEN7_GMU_GMU2HOST_INTR_CLR, UINT_MAX);
  260. gmu_core_regwrite(device, GEN7_GMU_GMU2HOST_INTR_MASK, HFI_IRQ_MASK);
  261. }