xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/midgard/mali_kbase_gator_api.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *
3  * (C) COPYRIGHT 2014-2017 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 
16 
17 
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 
24 #define MALI_MAX_CORES_PER_GROUP		4
25 #define MALI_MAX_NUM_BLOCKS_PER_GROUP	8
26 #define MALI_COUNTERS_PER_BLOCK			64
27 #define MALI_BYTES_PER_COUNTER			4
28 
29 struct kbase_gator_hwcnt_handles {
30 	struct kbase_device *kbdev;
31 	struct kbase_vinstr_client *vinstr_cli;
32 	void *vinstr_buffer;
33 	struct work_struct dump_work;
34 	int dump_complete;
35 	spinlock_t dump_lock;
36 };
37 
38 static void dump_worker(struct work_struct *work);
39 
kbase_gator_hwcnt_init_names(uint32_t * total_counters)40 const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters)
41 {
42 	const char * const *hardware_counters;
43 	struct kbase_device *kbdev;
44 	uint32_t product_id;
45 	uint32_t count;
46 
47 	if (!total_counters)
48 		return NULL;
49 
50 	/* Get the first device - it doesn't matter in this case */
51 	kbdev = kbase_find_device(-1);
52 	if (!kbdev)
53 		return NULL;
54 
55 	product_id = kbdev->gpu_props.props.core_props.product_id;
56 
57 	if (GPU_ID_IS_NEW_FORMAT(product_id)) {
58 		switch (GPU_ID2_MODEL_MATCH_VALUE(product_id)) {
59 		case GPU_ID2_PRODUCT_TMIX:
60 			hardware_counters = hardware_counters_mali_tMIx;
61 			count = ARRAY_SIZE(hardware_counters_mali_tMIx);
62 			break;
63 		case GPU_ID2_PRODUCT_THEX:
64 			hardware_counters = hardware_counters_mali_tHEx;
65 			count = ARRAY_SIZE(hardware_counters_mali_tHEx);
66 			break;
67 		case GPU_ID2_PRODUCT_TSIX:
68 			hardware_counters = hardware_counters_mali_tSIx;
69 			count = ARRAY_SIZE(hardware_counters_mali_tSIx);
70 			break;
71 		default:
72 			hardware_counters = NULL;
73 			count = 0;
74 			dev_err(kbdev->dev, "Unrecognized product ID: %u\n",
75 				product_id);
76 			break;
77 		}
78 	} else {
79 		switch (product_id) {
80 			/* If we are using a Mali-T60x device */
81 		case GPU_ID_PI_T60X:
82 			hardware_counters = hardware_counters_mali_t60x;
83 			count = ARRAY_SIZE(hardware_counters_mali_t60x);
84 			break;
85 			/* If we are using a Mali-T62x device */
86 		case GPU_ID_PI_T62X:
87 			hardware_counters = hardware_counters_mali_t62x;
88 			count = ARRAY_SIZE(hardware_counters_mali_t62x);
89 			break;
90 			/* If we are using a Mali-T72x device */
91 		case GPU_ID_PI_T72X:
92 			hardware_counters = hardware_counters_mali_t72x;
93 			count = ARRAY_SIZE(hardware_counters_mali_t72x);
94 			break;
95 			/* If we are using a Mali-T76x device */
96 		case GPU_ID_PI_T76X:
97 			hardware_counters = hardware_counters_mali_t76x;
98 			count = ARRAY_SIZE(hardware_counters_mali_t76x);
99 			break;
100 			/* If we are using a Mali-T82x device */
101 		case GPU_ID_PI_T82X:
102 			hardware_counters = hardware_counters_mali_t82x;
103 			count = ARRAY_SIZE(hardware_counters_mali_t82x);
104 			break;
105 			/* If we are using a Mali-T83x device */
106 		case GPU_ID_PI_T83X:
107 			hardware_counters = hardware_counters_mali_t83x;
108 			count = ARRAY_SIZE(hardware_counters_mali_t83x);
109 			break;
110 			/* If we are using a Mali-T86x device */
111 		case GPU_ID_PI_T86X:
112 			hardware_counters = hardware_counters_mali_t86x;
113 			count = ARRAY_SIZE(hardware_counters_mali_t86x);
114 			break;
115 			/* If we are using a Mali-T88x device */
116 		case GPU_ID_PI_TFRX:
117 			hardware_counters = hardware_counters_mali_t88x;
118 			count = ARRAY_SIZE(hardware_counters_mali_t88x);
119 			break;
120 		default:
121 			hardware_counters = NULL;
122 			count = 0;
123 			dev_err(kbdev->dev, "Unrecognized product ID: %u\n",
124 				product_id);
125 			break;
126 		}
127 	}
128 
129 	/* Release the kbdev reference. */
130 	kbase_release_device(kbdev);
131 
132 	*total_counters = count;
133 
134 	/* If we return a string array take a reference on the module (or fail). */
135 	if (hardware_counters && !try_module_get(THIS_MODULE))
136 		return NULL;
137 
138 	return hardware_counters;
139 }
140 KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init_names);
141 
kbase_gator_hwcnt_term_names(void)142 void kbase_gator_hwcnt_term_names(void)
143 {
144 	/* Release the module reference. */
145 	module_put(THIS_MODULE);
146 }
147 KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term_names);
148 
kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info * in_out_info)149 struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info)
150 {
151 	struct kbase_gator_hwcnt_handles *hand;
152 	struct kbase_uk_hwcnt_reader_setup setup;
153 	uint32_t dump_size = 0, i = 0;
154 
155 	if (!in_out_info)
156 		return NULL;
157 
158 	hand = kzalloc(sizeof(*hand), GFP_KERNEL);
159 	if (!hand)
160 		return NULL;
161 
162 	INIT_WORK(&hand->dump_work, dump_worker);
163 	spin_lock_init(&hand->dump_lock);
164 
165 	/* Get the first device */
166 	hand->kbdev = kbase_find_device(-1);
167 	if (!hand->kbdev)
168 		goto free_hand;
169 
170 	dump_size = kbase_vinstr_dump_size(hand->kbdev);
171 	hand->vinstr_buffer = kzalloc(dump_size, GFP_KERNEL);
172 	if (!hand->vinstr_buffer)
173 		goto release_device;
174 	in_out_info->kernel_dump_buffer = hand->vinstr_buffer;
175 
176 	in_out_info->nr_cores = hand->kbdev->gpu_props.num_cores;
177 	in_out_info->nr_core_groups = hand->kbdev->gpu_props.num_core_groups;
178 	in_out_info->gpu_id = hand->kbdev->gpu_props.props.core_props.product_id;
179 
180 	/* If we are using a v4 device (Mali-T6xx or Mali-T72x) */
181 	if (kbase_hw_has_feature(hand->kbdev, BASE_HW_FEATURE_V4)) {
182 		uint32_t cg, j;
183 		uint64_t core_mask;
184 
185 		/* There are 8 hardware counters blocks per core group */
186 		in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) *
187 			MALI_MAX_NUM_BLOCKS_PER_GROUP *
188 			in_out_info->nr_core_groups, GFP_KERNEL);
189 
190 		if (!in_out_info->hwc_layout)
191 			goto free_vinstr_buffer;
192 
193 		dump_size = in_out_info->nr_core_groups *
194 			MALI_MAX_NUM_BLOCKS_PER_GROUP *
195 			MALI_COUNTERS_PER_BLOCK *
196 			MALI_BYTES_PER_COUNTER;
197 
198 		for (cg = 0; cg < in_out_info->nr_core_groups; cg++) {
199 			core_mask = hand->kbdev->gpu_props.props.coherency_info.group[cg].core_mask;
200 
201 			for (j = 0; j < MALI_MAX_CORES_PER_GROUP; j++) {
202 				if (core_mask & (1u << j))
203 					in_out_info->hwc_layout[i++] = SHADER_BLOCK;
204 				else
205 					in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
206 			}
207 
208 			in_out_info->hwc_layout[i++] = TILER_BLOCK;
209 			in_out_info->hwc_layout[i++] = MMU_L2_BLOCK;
210 
211 			in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
212 
213 			if (0 == cg)
214 				in_out_info->hwc_layout[i++] = JM_BLOCK;
215 			else
216 				in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
217 		}
218 	/* If we are using any other device */
219 	} else {
220 		uint32_t nr_l2, nr_sc_bits, j;
221 		uint64_t core_mask;
222 
223 		nr_l2 = hand->kbdev->gpu_props.props.l2_props.num_l2_slices;
224 
225 		core_mask = hand->kbdev->gpu_props.props.coherency_info.group[0].core_mask;
226 
227 		nr_sc_bits = fls64(core_mask);
228 
229 		/* The job manager and tiler sets of counters
230 		 * are always present */
231 		in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) * (2 + nr_sc_bits + nr_l2), GFP_KERNEL);
232 
233 		if (!in_out_info->hwc_layout)
234 			goto free_vinstr_buffer;
235 
236 		dump_size = (2 + nr_sc_bits + nr_l2) * MALI_COUNTERS_PER_BLOCK * MALI_BYTES_PER_COUNTER;
237 
238 		in_out_info->hwc_layout[i++] = JM_BLOCK;
239 		in_out_info->hwc_layout[i++] = TILER_BLOCK;
240 
241 		for (j = 0; j < nr_l2; j++)
242 			in_out_info->hwc_layout[i++] = MMU_L2_BLOCK;
243 
244 		while (core_mask != 0ull) {
245 			if ((core_mask & 1ull) != 0ull)
246 				in_out_info->hwc_layout[i++] = SHADER_BLOCK;
247 			else
248 				in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
249 			core_mask >>= 1;
250 		}
251 	}
252 
253 	in_out_info->nr_hwc_blocks = i;
254 	in_out_info->size = dump_size;
255 
256 	setup.jm_bm = in_out_info->bitmask[0];
257 	setup.tiler_bm = in_out_info->bitmask[1];
258 	setup.shader_bm = in_out_info->bitmask[2];
259 	setup.mmu_l2_bm = in_out_info->bitmask[3];
260 	hand->vinstr_cli = kbase_vinstr_hwcnt_kernel_setup(hand->kbdev->vinstr_ctx,
261 			&setup, hand->vinstr_buffer);
262 	if (!hand->vinstr_cli) {
263 		dev_err(hand->kbdev->dev, "Failed to register gator with vinstr core");
264 		goto free_layout;
265 	}
266 
267 	return hand;
268 
269 free_layout:
270 	kfree(in_out_info->hwc_layout);
271 
272 free_vinstr_buffer:
273 	kfree(hand->vinstr_buffer);
274 
275 release_device:
276 	kbase_release_device(hand->kbdev);
277 
278 free_hand:
279 	kfree(hand);
280 	return NULL;
281 }
282 KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init);
283 
kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info * in_out_info,struct kbase_gator_hwcnt_handles * opaque_handles)284 void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles)
285 {
286 	if (in_out_info)
287 		kfree(in_out_info->hwc_layout);
288 
289 	if (opaque_handles) {
290 		cancel_work_sync(&opaque_handles->dump_work);
291 		kbase_vinstr_detach_client(opaque_handles->vinstr_cli);
292 		kfree(opaque_handles->vinstr_buffer);
293 		kbase_release_device(opaque_handles->kbdev);
294 		kfree(opaque_handles);
295 	}
296 }
297 KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term);
298 
dump_worker(struct work_struct * work)299 static void dump_worker(struct work_struct *work)
300 {
301 	struct kbase_gator_hwcnt_handles *hand;
302 
303 	hand = container_of(work, struct kbase_gator_hwcnt_handles, dump_work);
304 	if (!kbase_vinstr_hwc_dump(hand->vinstr_cli,
305 			BASE_HWCNT_READER_EVENT_MANUAL)) {
306 		spin_lock_bh(&hand->dump_lock);
307 		hand->dump_complete = 1;
308 		spin_unlock_bh(&hand->dump_lock);
309 	} else {
310 		schedule_work(&hand->dump_work);
311 	}
312 }
313 
kbase_gator_instr_hwcnt_dump_complete(struct kbase_gator_hwcnt_handles * opaque_handles,uint32_t * const success)314 uint32_t kbase_gator_instr_hwcnt_dump_complete(
315 		struct kbase_gator_hwcnt_handles *opaque_handles,
316 		uint32_t * const success)
317 {
318 
319 	if (opaque_handles && success) {
320 		*success = opaque_handles->dump_complete;
321 		opaque_handles->dump_complete = 0;
322 		return *success;
323 	}
324 	return 0;
325 }
326 KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_complete);
327 
kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles * opaque_handles)328 uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles)
329 {
330 	if (opaque_handles)
331 		schedule_work(&opaque_handles->dump_work);
332 	return 0;
333 }
334 KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_irq);
335