3 * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved.
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
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.
18 #include "mali_kbase.h"
19 #include "mali_kbase_hw.h"
20 #include "mali_kbase_mem_linux.h"
21 #include "mali_kbase_gator_api.h"
22 #include "mali_kbase_gator_hwcnt_names.h"
23 #include "mali_kbase_instr.h"
25 #define MALI_MAX_CORES_PER_GROUP 4
26 #define MALI_MAX_NUM_BLOCKS_PER_GROUP 8
27 #define MALI_COUNTERS_PER_BLOCK 64
28 #define MALI_BYTES_PER_COUNTER 4
30 struct kbase_gator_hwcnt_handles {
31 struct kbase_device *kbdev;
32 struct kbase_context *kctx;
35 struct kbase_vmap_struct hwcnt_map;
38 const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters)
41 const char * const *hardware_counters;
42 struct kbase_device *kbdev;
47 /* Get the first device - it doesn't matter in this case */
48 kbdev = kbase_find_device(-1);
52 gpu_id = kbdev->gpu_props.props.core_props.product_id;
55 /* If we are using a Mali-T60x device */
57 hardware_counters = hardware_counters_mali_t60x;
58 *total_counters = ARRAY_SIZE(hardware_counters_mali_t60x);
60 /* If we are using a Mali-T62x device */
62 hardware_counters = hardware_counters_mali_t62x;
63 *total_counters = ARRAY_SIZE(hardware_counters_mali_t62x);
65 /* If we are using a Mali-T72x device */
67 hardware_counters = hardware_counters_mali_t72x;
68 *total_counters = ARRAY_SIZE(hardware_counters_mali_t72x);
70 /* If we are using a Mali-T76x device */
72 hardware_counters = hardware_counters_mali_t76x;
73 *total_counters = ARRAY_SIZE(hardware_counters_mali_t76x);
75 /* If we are using a Mali-T82x device */
77 hardware_counters = hardware_counters_mali_t82x;
78 *total_counters = ARRAY_SIZE(hardware_counters_mali_t82x);
80 /* If we are using a Mali-T83x device */
82 hardware_counters = hardware_counters_mali_t83x;
83 *total_counters = ARRAY_SIZE(hardware_counters_mali_t83x);
85 /* If we are using a Mali-T86x device */
87 hardware_counters = hardware_counters_mali_t86x;
88 *total_counters = ARRAY_SIZE(hardware_counters_mali_t86x);
90 /* If we are using a Mali-T88x device */
92 hardware_counters = hardware_counters_mali_t88x;
93 *total_counters = ARRAY_SIZE(hardware_counters_mali_t88x);
96 hardware_counters = NULL;
98 dev_err(kbdev->dev, "Unrecognized gpu ID: %u\n", gpu_id);
102 /* Release the kbdev reference. */
103 kbase_release_device(kbdev);
105 /* If we return a string array take a reference on the module (or fail). */
106 if (hardware_counters && !try_module_get(THIS_MODULE))
109 return hardware_counters;
111 KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init_names);
113 void kbase_gator_hwcnt_term_names(void)
115 /* Release the module reference. */
116 module_put(THIS_MODULE);
118 KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term_names);
120 struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info)
122 struct kbase_gator_hwcnt_handles *hand;
123 struct kbase_uk_hwcnt_setup setup;
125 uint32_t dump_size = 0, i = 0;
126 struct kbase_va_region *reg;
129 u16 va_alignment = 0;
134 hand = kzalloc(sizeof(*hand), GFP_KERNEL);
138 /* Get the first device */
139 hand->kbdev = kbase_find_device(-1);
143 /* Create a kbase_context */
144 hand->kctx = kbase_create_context(hand->kbdev, true);
148 in_out_info->nr_cores = hand->kbdev->gpu_props.num_cores;
149 in_out_info->nr_core_groups = hand->kbdev->gpu_props.num_core_groups;
150 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)) {
157 /* There are 8 hardware counters blocks per core group */
158 in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) *
159 MALI_MAX_NUM_BLOCKS_PER_GROUP *
160 in_out_info->nr_core_groups, GFP_KERNEL);
162 if (!in_out_info->hwc_layout)
163 goto destroy_context;
165 dump_size = in_out_info->nr_core_groups *
166 MALI_MAX_NUM_BLOCKS_PER_GROUP *
167 MALI_COUNTERS_PER_BLOCK *
168 MALI_BYTES_PER_COUNTER;
170 for (cg = 0; cg < in_out_info->nr_core_groups; cg++) {
171 core_mask = hand->kbdev->gpu_props.props.coherency_info.group[cg].core_mask;
173 for (j = 0; j < MALI_MAX_CORES_PER_GROUP; j++) {
174 if (core_mask & (1u << j))
175 in_out_info->hwc_layout[i++] = SHADER_BLOCK;
177 in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
180 in_out_info->hwc_layout[i++] = TILER_BLOCK;
181 in_out_info->hwc_layout[i++] = MMU_L2_BLOCK;
183 in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
186 in_out_info->hwc_layout[i++] = JM_BLOCK;
188 in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
190 /* If we are using any other device */
192 uint32_t nr_l2, nr_sc_bits, j;
195 nr_l2 = hand->kbdev->gpu_props.props.l2_props.num_l2_slices;
197 core_mask = hand->kbdev->gpu_props.props.coherency_info.group[0].core_mask;
199 nr_sc_bits = fls64(core_mask);
201 /* The job manager and tiler sets of counters
202 * are always present */
203 in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) * (2 + nr_sc_bits + nr_l2), GFP_KERNEL);
205 if (!in_out_info->hwc_layout)
206 goto destroy_context;
208 dump_size = (2 + nr_sc_bits + nr_l2) * MALI_COUNTERS_PER_BLOCK * MALI_BYTES_PER_COUNTER;
210 in_out_info->hwc_layout[i++] = JM_BLOCK;
211 in_out_info->hwc_layout[i++] = TILER_BLOCK;
213 for (j = 0; j < nr_l2; j++)
214 in_out_info->hwc_layout[i++] = MMU_L2_BLOCK;
216 while (core_mask != 0ull) {
217 if ((core_mask & 1ull) != 0ull)
218 in_out_info->hwc_layout[i++] = SHADER_BLOCK;
220 in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
225 in_out_info->nr_hwc_blocks = i;
227 in_out_info->size = dump_size;
229 flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_CPU_WR | BASE_MEM_PROT_GPU_WR;
230 nr_pages = PFN_UP(dump_size);
231 reg = kbase_mem_alloc(hand->kctx, nr_pages, nr_pages, 0,
232 &flags, &hand->hwcnt_gpu_va, &va_alignment);
236 hand->hwcnt_cpu_va = kbase_vmap(hand->kctx, hand->hwcnt_gpu_va,
237 dump_size, &hand->hwcnt_map);
239 if (!hand->hwcnt_cpu_va)
242 in_out_info->kernel_dump_buffer = hand->hwcnt_cpu_va;
243 memset(in_out_info->kernel_dump_buffer, 0, nr_pages * PAGE_SIZE);
245 /*setup.dump_buffer = (uintptr_t)in_out_info->kernel_dump_buffer;*/
246 setup.dump_buffer = hand->hwcnt_gpu_va;
247 setup.jm_bm = in_out_info->bitmask[0];
248 setup.tiler_bm = in_out_info->bitmask[1];
249 setup.shader_bm = in_out_info->bitmask[2];
250 setup.mmu_l2_bm = in_out_info->bitmask[3];
252 err = kbase_instr_hwcnt_enable(hand->kctx, &setup);
256 kbase_instr_hwcnt_clear(hand->kctx);
261 kbase_vunmap(hand->kctx, &hand->hwcnt_map);
264 kbase_mem_free(hand->kctx, hand->hwcnt_gpu_va);
267 kfree(in_out_info->hwc_layout);
270 kbase_destroy_context(hand->kctx);
273 kbase_release_device(hand->kbdev);
280 KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init);
282 void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles)
285 kfree(in_out_info->hwc_layout);
287 if (opaque_handles) {
288 kbase_instr_hwcnt_disable(opaque_handles->kctx);
289 kbase_vunmap(opaque_handles->kctx, &opaque_handles->hwcnt_map);
290 kbase_mem_free(opaque_handles->kctx, opaque_handles->hwcnt_gpu_va);
291 kbase_destroy_context(opaque_handles->kctx);
292 kbase_release_device(opaque_handles->kbdev);
293 kfree(opaque_handles);
296 KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term);
298 uint32_t kbase_gator_instr_hwcnt_dump_complete(
299 struct kbase_gator_hwcnt_handles *opaque_handles,
300 uint32_t * const success)
302 bool ret_res, success_res;
304 if (opaque_handles && success) {
305 ret_res = kbase_instr_hwcnt_dump_complete(opaque_handles->kctx,
307 *success = (uint32_t)success_res;
308 return (uint32_t)(ret_res != 0);
312 KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_complete);
314 uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles)
317 return (kbase_instr_hwcnt_request_dump(
318 opaque_handles->kctx) == 0);
322 KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_irq);