mali_kbase_gator_api.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. *
  3. * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved.
  4. *
  5. * This program is free software and is provided to you under the terms of the
  6. * GNU General Public License version 2 as published by the Free Software
  7. * Foundation, and any use by you of this program is subject to the terms
  8. * of such GNU licence.
  9. *
  10. * A copy of the licence is included with the program, and can also be obtained
  11. * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  12. * Boston, MA 02110-1301, USA.
  13. *
  14. */
  15. #include "mali_kbase.h"
  16. #include "mali_kbase_hw.h"
  17. #include "mali_kbase_mem_linux.h"
  18. #include "mali_kbase_gator_api.h"
  19. #include "mali_kbase_gator_hwcnt_names.h"
  20. #include "mali_kbase_instr.h"
  21. #define MALI_MAX_CORES_PER_GROUP 4
  22. #define MALI_MAX_NUM_BLOCKS_PER_GROUP 8
  23. #define MALI_COUNTERS_PER_BLOCK 64
  24. #define MALI_BYTES_PER_COUNTER 4
  25. struct kbase_gator_hwcnt_handles {
  26. struct kbase_device *kbdev;
  27. struct kbase_vinstr_client *vinstr_cli;
  28. void *vinstr_buffer;
  29. struct work_struct dump_work;
  30. int dump_complete;
  31. spinlock_t dump_lock;
  32. };
  33. static void dump_worker(struct work_struct *work);
  34. const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters)
  35. {
  36. const char * const *hardware_counters;
  37. struct kbase_device *kbdev;
  38. uint32_t gpu_id;
  39. uint32_t product_id;
  40. uint32_t count;
  41. if (!total_counters)
  42. return NULL;
  43. /* Get the first device - it doesn't matter in this case */
  44. kbdev = kbase_find_device(-1);
  45. if (!kbdev)
  46. return NULL;
  47. gpu_id = kbdev->gpu_props.props.core_props.product_id;
  48. product_id = gpu_id & GPU_ID_VERSION_PRODUCT_ID;
  49. product_id >>= GPU_ID_VERSION_PRODUCT_ID_SHIFT;
  50. if (GPU_ID_IS_NEW_FORMAT(product_id)) {
  51. switch (gpu_id & GPU_ID2_PRODUCT_MODEL) {
  52. case GPU_ID2_PRODUCT_TMIX:
  53. hardware_counters = hardware_counters_mali_tMIx;
  54. count = ARRAY_SIZE(hardware_counters_mali_tMIx);
  55. break;
  56. default:
  57. hardware_counters = NULL;
  58. count = 0;
  59. dev_err(kbdev->dev, "Unrecognized gpu ID: %u\n",
  60. gpu_id);
  61. break;
  62. }
  63. } else {
  64. switch (gpu_id) {
  65. /* If we are using a Mali-T60x device */
  66. case GPU_ID_PI_T60X:
  67. hardware_counters = hardware_counters_mali_t60x;
  68. count = ARRAY_SIZE(hardware_counters_mali_t60x);
  69. break;
  70. /* If we are using a Mali-T62x device */
  71. case GPU_ID_PI_T62X:
  72. hardware_counters = hardware_counters_mali_t62x;
  73. count = ARRAY_SIZE(hardware_counters_mali_t62x);
  74. break;
  75. /* If we are using a Mali-T72x device */
  76. case GPU_ID_PI_T72X:
  77. hardware_counters = hardware_counters_mali_t72x;
  78. count = ARRAY_SIZE(hardware_counters_mali_t72x);
  79. break;
  80. /* If we are using a Mali-T76x device */
  81. case GPU_ID_PI_T76X:
  82. hardware_counters = hardware_counters_mali_t76x;
  83. count = ARRAY_SIZE(hardware_counters_mali_t76x);
  84. break;
  85. /* If we are using a Mali-T82x device */
  86. case GPU_ID_PI_T82X:
  87. hardware_counters = hardware_counters_mali_t82x;
  88. count = ARRAY_SIZE(hardware_counters_mali_t82x);
  89. break;
  90. /* If we are using a Mali-T83x device */
  91. case GPU_ID_PI_T83X:
  92. hardware_counters = hardware_counters_mali_t83x;
  93. count = ARRAY_SIZE(hardware_counters_mali_t83x);
  94. break;
  95. /* If we are using a Mali-T86x device */
  96. case GPU_ID_PI_T86X:
  97. hardware_counters = hardware_counters_mali_t86x;
  98. count = ARRAY_SIZE(hardware_counters_mali_t86x);
  99. break;
  100. /* If we are using a Mali-T88x device */
  101. case GPU_ID_PI_TFRX:
  102. hardware_counters = hardware_counters_mali_t88x;
  103. count = ARRAY_SIZE(hardware_counters_mali_t88x);
  104. break;
  105. default:
  106. hardware_counters = NULL;
  107. count = 0;
  108. dev_err(kbdev->dev, "Unrecognized gpu ID: %u\n",
  109. gpu_id);
  110. break;
  111. }
  112. }
  113. /* Release the kbdev reference. */
  114. kbase_release_device(kbdev);
  115. *total_counters = count;
  116. /* If we return a string array take a reference on the module (or fail). */
  117. if (hardware_counters && !try_module_get(THIS_MODULE))
  118. return NULL;
  119. return hardware_counters;
  120. }
  121. KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init_names);
  122. void kbase_gator_hwcnt_term_names(void)
  123. {
  124. /* Release the module reference. */
  125. module_put(THIS_MODULE);
  126. }
  127. KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term_names);
  128. struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info)
  129. {
  130. struct kbase_gator_hwcnt_handles *hand;
  131. struct kbase_uk_hwcnt_reader_setup setup;
  132. uint32_t dump_size = 0, i = 0;
  133. if (!in_out_info)
  134. return NULL;
  135. hand = kzalloc(sizeof(*hand), GFP_KERNEL);
  136. if (!hand)
  137. return NULL;
  138. INIT_WORK(&hand->dump_work, dump_worker);
  139. spin_lock_init(&hand->dump_lock);
  140. /* Get the first device */
  141. hand->kbdev = kbase_find_device(-1);
  142. if (!hand->kbdev)
  143. goto free_hand;
  144. dump_size = kbase_vinstr_dump_size(hand->kbdev);
  145. hand->vinstr_buffer = kzalloc(dump_size, GFP_KERNEL);
  146. if (!hand->vinstr_buffer)
  147. goto release_device;
  148. in_out_info->kernel_dump_buffer = hand->vinstr_buffer;
  149. in_out_info->nr_cores = hand->kbdev->gpu_props.num_cores;
  150. in_out_info->nr_core_groups = hand->kbdev->gpu_props.num_core_groups;
  151. in_out_info->gpu_id = hand->kbdev->gpu_props.props.core_props.product_id;
  152. /* If we are using a v4 device (Mali-T6xx or Mali-T72x) */
  153. if (kbase_hw_has_feature(hand->kbdev, BASE_HW_FEATURE_V4)) {
  154. uint32_t cg, j;
  155. uint64_t core_mask;
  156. /* There are 8 hardware counters blocks per core group */
  157. in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) *
  158. MALI_MAX_NUM_BLOCKS_PER_GROUP *
  159. in_out_info->nr_core_groups, GFP_KERNEL);
  160. if (!in_out_info->hwc_layout)
  161. goto free_vinstr_buffer;
  162. dump_size = in_out_info->nr_core_groups *
  163. MALI_MAX_NUM_BLOCKS_PER_GROUP *
  164. MALI_COUNTERS_PER_BLOCK *
  165. MALI_BYTES_PER_COUNTER;
  166. for (cg = 0; cg < in_out_info->nr_core_groups; cg++) {
  167. core_mask = hand->kbdev->gpu_props.props.coherency_info.group[cg].core_mask;
  168. for (j = 0; j < MALI_MAX_CORES_PER_GROUP; j++) {
  169. if (core_mask & (1u << j))
  170. in_out_info->hwc_layout[i++] = SHADER_BLOCK;
  171. else
  172. in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
  173. }
  174. in_out_info->hwc_layout[i++] = TILER_BLOCK;
  175. in_out_info->hwc_layout[i++] = MMU_L2_BLOCK;
  176. in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
  177. if (0 == cg)
  178. in_out_info->hwc_layout[i++] = JM_BLOCK;
  179. else
  180. in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
  181. }
  182. /* If we are using any other device */
  183. } else {
  184. uint32_t nr_l2, nr_sc_bits, j;
  185. uint64_t core_mask;
  186. nr_l2 = hand->kbdev->gpu_props.props.l2_props.num_l2_slices;
  187. core_mask = hand->kbdev->gpu_props.props.coherency_info.group[0].core_mask;
  188. nr_sc_bits = fls64(core_mask);
  189. /* The job manager and tiler sets of counters
  190. * are always present */
  191. in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) * (2 + nr_sc_bits + nr_l2), GFP_KERNEL);
  192. if (!in_out_info->hwc_layout)
  193. goto free_vinstr_buffer;
  194. dump_size = (2 + nr_sc_bits + nr_l2) * MALI_COUNTERS_PER_BLOCK * MALI_BYTES_PER_COUNTER;
  195. in_out_info->hwc_layout[i++] = JM_BLOCK;
  196. in_out_info->hwc_layout[i++] = TILER_BLOCK;
  197. for (j = 0; j < nr_l2; j++)
  198. in_out_info->hwc_layout[i++] = MMU_L2_BLOCK;
  199. while (core_mask != 0ull) {
  200. if ((core_mask & 1ull) != 0ull)
  201. in_out_info->hwc_layout[i++] = SHADER_BLOCK;
  202. else
  203. in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
  204. core_mask >>= 1;
  205. }
  206. }
  207. in_out_info->nr_hwc_blocks = i;
  208. in_out_info->size = dump_size;
  209. setup.jm_bm = in_out_info->bitmask[0];
  210. setup.tiler_bm = in_out_info->bitmask[1];
  211. setup.shader_bm = in_out_info->bitmask[2];
  212. setup.mmu_l2_bm = in_out_info->bitmask[3];
  213. hand->vinstr_cli = kbase_vinstr_hwcnt_kernel_setup(hand->kbdev->vinstr_ctx,
  214. &setup, hand->vinstr_buffer);
  215. if (!hand->vinstr_cli) {
  216. dev_err(hand->kbdev->dev, "Failed to register gator with vinstr core");
  217. goto free_layout;
  218. }
  219. return hand;
  220. free_layout:
  221. kfree(in_out_info->hwc_layout);
  222. free_vinstr_buffer:
  223. kfree(hand->vinstr_buffer);
  224. release_device:
  225. kbase_release_device(hand->kbdev);
  226. free_hand:
  227. kfree(hand);
  228. return NULL;
  229. }
  230. KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init);
  231. void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles)
  232. {
  233. if (in_out_info)
  234. kfree(in_out_info->hwc_layout);
  235. if (opaque_handles) {
  236. cancel_work_sync(&opaque_handles->dump_work);
  237. kbase_vinstr_detach_client(opaque_handles->vinstr_cli);
  238. kfree(opaque_handles->vinstr_buffer);
  239. kbase_release_device(opaque_handles->kbdev);
  240. kfree(opaque_handles);
  241. }
  242. }
  243. KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term);
  244. static void dump_worker(struct work_struct *work)
  245. {
  246. struct kbase_gator_hwcnt_handles *hand;
  247. hand = container_of(work, struct kbase_gator_hwcnt_handles, dump_work);
  248. if (!kbase_vinstr_hwc_dump(hand->vinstr_cli,
  249. BASE_HWCNT_READER_EVENT_MANUAL)) {
  250. spin_lock_bh(&hand->dump_lock);
  251. hand->dump_complete = 1;
  252. spin_unlock_bh(&hand->dump_lock);
  253. } else {
  254. schedule_work(&hand->dump_work);
  255. }
  256. }
  257. uint32_t kbase_gator_instr_hwcnt_dump_complete(
  258. struct kbase_gator_hwcnt_handles *opaque_handles,
  259. uint32_t * const success)
  260. {
  261. if (opaque_handles && success) {
  262. *success = opaque_handles->dump_complete;
  263. opaque_handles->dump_complete = 0;
  264. return *success;
  265. }
  266. return 0;
  267. }
  268. KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_complete);
  269. uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles)
  270. {
  271. if (opaque_handles)
  272. schedule_work(&opaque_handles->dump_work);
  273. return 0;
  274. }
  275. KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_irq);