1 /**
2 * Copyright (C) ARM Limited 2010-2012. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
9 #include "gator.h"
11 #include <linux/module.h>
12 #include <linux/time.h>
13 #include <linux/math64.h>
15 #include "linux/mali_linux_trace.h"
17 /*
18 * There are (currently) three different variants of the comms between gator and Mali:
19 * 1 (deprecated): No software counter support
20 * 2 (deprecated): Tracepoint called for each separate s/w counter value as it appears
21 * 3 (default): Single tracepoint for all s/w counters in a bundle.
22 * Interface style 3 is the default if no other is specified. 1 and 2 will be eliminated when
23 * existing Mali DDKs are upgraded.
24 */
26 #if !defined(GATOR_MALI_INTERFACE_STYLE)
27 #define GATOR_MALI_INTERFACE_STYLE (3)
28 #endif
30 #define MALI_200 (0x0a07)
31 #define MALI_300 (0x0b06) //This is not actually true; Mali-300 is also 0x0b07
32 #define MALI_400 (0x0b07)
33 #define MALI_T6xx (0x0056)
35 /*
36 * List of possible actions allowing DDK to be controlled by Streamline.
37 * The following numbers are used by DDK to control the frame buffer dumping.
38 */
39 #define FBDUMP_CONTROL_ENABLE (1)
40 #define FBDUMP_CONTROL_RATE (2)
41 #define SW_EVENTS_ENABLE (3)
42 #define FBDUMP_CONTROL_RESIZE_FACTOR (4)
44 /*
45 * Check that the MALI_SUPPORT define is set to one of the allowable device codes.
46 */
47 #if !defined(MALI_SUPPORT)
48 #error MALI_SUPPORT not defined!
49 #elif (MALI_SUPPORT != MALI_200) && (MALI_SUPPORT != MALI_300) && (MALI_SUPPORT != MALI_400) && (MALI_SUPPORT != MALI_T6xx)
50 #error MALI_SUPPORT set to an invalid device code
51 #endif
53 static const char *mali_name;
55 enum counters {
56 /* Timeline activity */
57 ACTIVITY_VP = 0,
58 ACTIVITY_FP0,
59 ACTIVITY_FP1,
60 ACTIVITY_FP2,
61 ACTIVITY_FP3,
63 /* L2 cache counters */
64 COUNTER_L2_C0,
65 COUNTER_L2_C1,
67 /* Vertex processor counters */
68 COUNTER_VP_C0,
69 COUNTER_VP_C1,
71 /* Fragment processor counters */
72 COUNTER_FP0_C0,
73 COUNTER_FP0_C1,
74 COUNTER_FP1_C0,
75 COUNTER_FP1_C1,
76 COUNTER_FP2_C0,
77 COUNTER_FP2_C1,
78 COUNTER_FP3_C0,
79 COUNTER_FP3_C1,
81 /* EGL Software Counters */
82 COUNTER_EGL_BLIT_TIME,
84 /* GLES Software Counters */
85 COUNTER_GLES_DRAW_ELEMENTS_CALLS,
86 COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES,
87 COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED,
88 COUNTER_GLES_DRAW_ARRAYS_CALLS,
89 COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED,
90 COUNTER_GLES_DRAW_POINTS,
91 COUNTER_GLES_DRAW_LINES,
92 COUNTER_GLES_DRAW_LINE_LOOP,
93 COUNTER_GLES_DRAW_LINE_STRIP,
94 COUNTER_GLES_DRAW_TRIANGLES,
95 COUNTER_GLES_DRAW_TRIANGLE_STRIP,
96 COUNTER_GLES_DRAW_TRIANGLE_FAN,
97 COUNTER_GLES_NON_VBO_DATA_COPY_TIME,
98 COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI,
99 COUNTER_GLES_UPLOAD_TEXTURE_TIME,
100 COUNTER_GLES_UPLOAD_VBO_TIME,
101 COUNTER_GLES_NUM_FLUSHES,
102 COUNTER_GLES_NUM_VSHADERS_GENERATED,
103 COUNTER_GLES_NUM_FSHADERS_GENERATED,
104 COUNTER_GLES_VSHADER_GEN_TIME,
105 COUNTER_GLES_FSHADER_GEN_TIME,
106 COUNTER_GLES_INPUT_TRIANGLES,
107 COUNTER_GLES_VXCACHE_HIT,
108 COUNTER_GLES_VXCACHE_MISS,
109 COUNTER_GLES_VXCACHE_COLLISION,
110 COUNTER_GLES_CULLED_TRIANGLES,
111 COUNTER_GLES_CULLED_LINES,
112 COUNTER_GLES_BACKFACE_TRIANGLES,
113 COUNTER_GLES_GBCLIP_TRIANGLES,
114 COUNTER_GLES_GBCLIP_LINES,
115 COUNTER_GLES_TRIANGLES_DRAWN,
116 COUNTER_GLES_DRAWCALL_TIME,
117 COUNTER_GLES_TRIANGLES_COUNT,
118 COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT,
119 COUNTER_GLES_STRIP_TRIANGLES_COUNT,
120 COUNTER_GLES_FAN_TRIANGLES_COUNT,
121 COUNTER_GLES_LINES_COUNT,
122 COUNTER_GLES_INDEPENDENT_LINES_COUNT,
123 COUNTER_GLES_STRIP_LINES_COUNT,
124 COUNTER_GLES_LOOP_LINES_COUNT,
126 COUNTER_FILMSTRIP,
128 NUMBER_OF_EVENTS
129 };
131 #define FIRST_ACTIVITY_EVENT ACTIVITY_VP
132 #define LAST_ACTIVITY_EVENT ACTIVITY_FP3
134 #define FIRST_HW_COUNTER COUNTER_L2_C0
135 #define LAST_HW_COUNTER COUNTER_FP3_C1
137 #define FIRST_SW_COUNTER COUNTER_EGL_BLIT_TIME
138 #define LAST_SW_COUNTER COUNTER_GLES_LOOP_LINES_COUNT
140 #define FIRST_SPECIAL_COUNTER COUNTER_FILMSTRIP
141 #define LAST_SPECIAL_COUNTER COUNTER_FILMSTRIP
143 /* gatorfs variables for counter enable state,
144 * the event the counter should count and the
145 * 'key' (a unique id set by gatord and returned
146 * by gator.ko)
147 */
148 static unsigned long counter_enabled[NUMBER_OF_EVENTS];
149 static unsigned long counter_event[NUMBER_OF_EVENTS];
150 static unsigned long counter_key[NUMBER_OF_EVENTS];
152 /* The data we have recorded */
153 static u32 counter_data[NUMBER_OF_EVENTS];
154 /* The address to sample (or 0 if samples are sent to us) */
155 static u32* counter_address[NUMBER_OF_EVENTS];
157 /* An array used to return the data we recorded
158 * as key,value pairs hence the *2
159 */
160 static unsigned long counter_dump[NUMBER_OF_EVENTS * 2];
161 static unsigned long counter_prev[NUMBER_OF_EVENTS];
163 /* Note whether tracepoints have been registered */
164 static int trace_registered;
166 /**
167 * Calculate the difference and handle the overflow.
168 */
169 static u32 get_difference(u32 start, u32 end)
170 {
171 if (start - end >= 0)
172 {
173 return start - end;
174 }
176 // Mali counters are unsigned 32 bit values that wrap.
177 return (4294967295u - end) + start;
178 }
180 /**
181 * Returns non-zero if the given counter ID is an activity counter.
182 */
183 static inline int is_activity_counter(unsigned int event_id)
184 {
185 return (event_id >= FIRST_ACTIVITY_EVENT &&
186 event_id <= LAST_ACTIVITY_EVENT);
187 }
189 /**
190 * Returns non-zero if the given counter ID is a hardware counter.
191 */
192 static inline int is_hw_counter(unsigned int event_id)
193 {
194 return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER);
195 }
197 /**
198 * Returns non-zero if the given counter ID is a software counter.
199 */
200 static inline int is_sw_counter(unsigned int event_id)
201 {
202 return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER);
203 }
205 /*
206 * The Mali DDK uses s64 types to contain software counter values, but gator
207 * can only use a maximum of 32 bits. This function scales a software counter
208 * to an appopriate range.
209 */
210 static u32 scale_sw_counter_value(unsigned int event_id, signed long long value)
211 {
212 u32 scaled_value;
214 switch (event_id) {
215 case COUNTER_GLES_UPLOAD_TEXTURE_TIME:
216 case COUNTER_GLES_UPLOAD_VBO_TIME:
217 scaled_value = (u32)div_s64(value, 1000000);
218 break;
219 default:
220 scaled_value = (u32)value;
221 break;
222 }
224 return scaled_value;
225 }
227 /* Probe for continuously sampled counter */
228 #if 0 //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING
229 GATOR_DEFINE_PROBE(mali_sample_address, TP_PROTO(unsigned int event_id, u32* addr))
230 {
231 /* Turning on too many pr_debug statements in frequently called functions
232 * can cause stability and/or performance problems
233 */
234 //pr_debug("gator: mali_sample_address %d %d\n", event_id, addr);
235 if (event_id >= ACTIVITY_VP && event_id <= COUNTER_FP3_C1) {
236 counter_address[event_id] = addr;
237 }
238 }
239 #endif
241 /* Probe for hardware counter events */
242 GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int value))
243 {
244 /* Turning on too many pr_debug statements in frequently called functions
245 * can cause stability and/or performance problems
246 */
247 //pr_debug("gator: mali_hw_counter %d %d\n", event_id, value);
248 if (is_hw_counter(event_id)) {
249 counter_data[event_id] = value;
250 }
251 }
253 #if GATOR_MALI_INTERFACE_STYLE == 2
254 GATOR_DEFINE_PROBE(mali_sw_counter, TP_PROTO(unsigned int event_id, signed long long value))
255 {
256 if (is_sw_counter(event_id)) {
257 counter_data[event_id] = scale_sw_counter_value(event_id, value);
258 }
259 }
260 #endif /* GATOR_MALI_INTERFACE_STYLE == 2 */
263 #if GATOR_MALI_INTERFACE_STYLE == 3
264 GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void * surface_id, unsigned int * counters))
265 {
266 u32 i;
268 /* Copy over the values for those counters which are enabled. */
269 for(i=FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++)
270 {
271 if(counter_enabled[i])
272 {
273 counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]);
274 }
275 }
276 }
277 #endif /* GATOR_MALI_INTERFACE_STYLE == 3 */
279 //TODO need to work out how many fp units we have
280 u32 gator_mali_get_n_fp(void) {
281 return 4;
282 }
284 //TODO need to work out what kind of Mali we are looking at
285 u32 gator_mali_get_id(void) {
286 return MALI_SUPPORT;
287 }
289 int gator_events_mali_create_files(struct super_block *sb, struct dentry *root) {
290 struct dentry *dir;
291 int event;
292 int n_fp = gator_mali_get_n_fp();
294 /*
295 * Create the filesystem entries for vertex processor, fragement processor
296 * and L2 cache timeline and hardware counters. Software counters get
297 * special handling after this block.
298 */
299 for (event = FIRST_ACTIVITY_EVENT; event <= LAST_HW_COUNTER; event++)
300 {
301 char buf[40];
303 /*
304 * We can skip this event if it's for a non-existent fragment
305 * processor.
306 */
307 if (((event - ACTIVITY_FP0 >= n_fp) && (event < COUNTER_L2_C0)) ||
308 (((event - COUNTER_FP0_C0)/2 >= n_fp)))
309 {
310 continue;
311 }
313 /* Otherwise, set up the filesystem entry for this event. */
314 switch (event) {
315 case ACTIVITY_VP:
316 snprintf(buf, sizeof buf, "ARM_%s_VP_active", mali_name);
317 break;
318 case ACTIVITY_FP0:
319 case ACTIVITY_FP1:
320 case ACTIVITY_FP2:
321 case ACTIVITY_FP3:
322 snprintf(buf, sizeof buf, "ARM_%s_FP%d_active",
323 mali_name, event - ACTIVITY_FP0);
324 break;
325 case COUNTER_L2_C0:
326 case COUNTER_L2_C1:
327 snprintf(buf, sizeof buf, "ARM_%s_L2_cnt%d",
328 mali_name, event - COUNTER_L2_C0);
329 break;
330 case COUNTER_VP_C0:
331 case COUNTER_VP_C1:
332 snprintf(buf, sizeof buf, "ARM_%s_VP_cnt%d",
333 mali_name, event - COUNTER_VP_C0);
334 break;
335 case COUNTER_FP0_C0:
336 case COUNTER_FP0_C1:
337 case COUNTER_FP1_C0:
338 case COUNTER_FP1_C1:
339 case COUNTER_FP2_C0:
340 case COUNTER_FP2_C1:
341 case COUNTER_FP3_C0:
342 case COUNTER_FP3_C1:
343 snprintf(buf, sizeof buf, "ARM_%s_FP%d_cnt%d", mali_name,
344 (event - COUNTER_FP0_C0) / 2, (event - COUNTER_FP0_C0) % 2);
345 break;
346 default:
347 printk("gator: trying to create file for non-existent counter (%d)\n", event);
348 continue;
349 }
351 dir = gatorfs_mkdir(sb, root, buf);
353 if (!dir) {
354 return -1;
355 }
357 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
359 /* Only create an event node for counters that can change what they count */
360 if (event >= COUNTER_L2_C0) {
361 gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
362 }
364 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
365 }
367 /* Now set up the software counter entries */
368 for (event = FIRST_SW_COUNTER; event <= LAST_SW_COUNTER; event++)
369 {
370 char buf[40];
372 snprintf(buf, sizeof(buf), "ARM_%s_SW_%d", mali_name, event);
374 dir = gatorfs_mkdir(sb, root, buf);
376 if (!dir) {
377 return -1;
378 }
380 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
381 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
382 }
384 /* Now set up the special counter entries */
385 for (event = FIRST_SPECIAL_COUNTER; event <= LAST_SPECIAL_COUNTER; event++)
386 {
387 char buf[40];
389 snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip", mali_name);
391 dir = gatorfs_mkdir(sb, root, buf);
393 if (!dir) {
394 return -1;
395 }
397 gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
398 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
399 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
400 }
403 return 0;
404 }
406 //TODO
407 void _mali_profiling_set_event(unsigned int, unsigned int);
408 void _mali_osk_fb_control_set(unsigned int, unsigned int);
409 void _mali_profiling_control(unsigned int, unsigned int);
411 void _mali_profiling_get_counters(unsigned int*, unsigned int*, unsigned int*, unsigned int*);
412 void (*_mali_profiling_get_counters_function_pointer)(unsigned int*, unsigned int*, unsigned int*, unsigned int*);
414 /*
415 * Examine list of software counters and determine if any one is enabled.
416 * Returns 1 if any counter is enabled, 0 if none is.
417 */
418 static int is_any_sw_counter_enabled(void)
419 {
420 unsigned int i;
422 for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++)
423 {
424 if (counter_enabled[i])
425 {
426 return 1; /* At least one counter is enabled */
427 }
428 }
430 return 0; /* No s/w counters enabled */
431 }
433 static void mali_counter_initialize(void)
434 {
435 /* If a Mali driver is present and exporting the appropriate symbol
436 * then we can request the HW counters (of which there are only 2)
437 * be configured to count the desired events
438 */
439 void (*set_hw_event)(unsigned int, unsigned int);
440 void (*set_fb_event)(unsigned int, unsigned int);
441 void (*mali_control)(unsigned int, unsigned int);
443 set_hw_event = symbol_get(_mali_profiling_set_event);
445 if (set_hw_event) {
446 int i;
448 pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n",set_hw_event);
450 for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
451 if (counter_enabled[i]) {
452 set_hw_event(i, counter_event[i]);
453 } else {
454 set_hw_event(i, 0xFFFFFFFF);
455 }
456 }
458 symbol_put(_mali_profiling_set_event);
459 } else {
460 printk("gator: mali online _mali_profiling_set_event symbol not found\n");
461 }
463 set_fb_event = symbol_get(_mali_osk_fb_control_set);
465 if (set_fb_event) {
466 pr_debug("gator: mali online _mali_osk_fb_control_set symbol @ %p\n", set_fb_event);
468 set_fb_event(0,(counter_enabled[COUNTER_FILMSTRIP]?1:0));
470 symbol_put(_mali_osk_fb_control_set);
471 } else {
472 printk("gator: mali online _mali_osk_fb_control_set symbol not found\n");
473 }
475 /* Generic control interface for Mali DDK. */
476 mali_control = symbol_get(_mali_profiling_control);
477 if (mali_control) {
478 /* The event attribute in the XML file keeps the actual frame rate. */
479 unsigned int rate = counter_event[COUNTER_FILMSTRIP] & 0xff;
480 unsigned int resize_factor = (counter_event[COUNTER_FILMSTRIP] >> 8) & 0xff;
482 pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control);
484 mali_control(SW_EVENTS_ENABLE, (is_any_sw_counter_enabled()?1:0));
485 mali_control(FBDUMP_CONTROL_ENABLE, (counter_enabled[COUNTER_FILMSTRIP]?1:0));
486 mali_control(FBDUMP_CONTROL_RATE, rate);
487 mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor);
489 pr_debug("gator: sent mali_control enabled=%d, rate=%d\n", (counter_enabled[COUNTER_FILMSTRIP]?1:0), rate);
491 symbol_put(_mali_profiling_control);
492 } else {
493 printk("gator: mali online _mali_profiling_control symbol not found\n");
494 }
496 _mali_profiling_get_counters_function_pointer = symbol_get(_mali_profiling_get_counters);
497 if (_mali_profiling_get_counters_function_pointer){
498 pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", _mali_profiling_get_counters_function_pointer);
499 counter_prev[COUNTER_L2_C0] = 0;
500 counter_prev[COUNTER_L2_C1] = 0;
501 }
502 else{
503 pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined");
504 }
505 }
507 static void mali_counter_deinitialize(void)
508 {
509 void (*set_hw_event)(unsigned int, unsigned int);
510 void (*set_fb_event)(unsigned int, unsigned int);
511 void (*mali_control)(unsigned int, unsigned int);
513 set_hw_event = symbol_get(_mali_profiling_set_event);
515 if (set_hw_event) {
516 int i;
518 pr_debug("gator: mali offline _mali_profiling_set_event symbol @ %p\n",set_hw_event);
519 for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
520 set_hw_event(i, 0xFFFFFFFF);
521 }
523 symbol_put(_mali_profiling_set_event);
524 } else {
525 printk("gator: mali offline _mali_profiling_set_event symbol not found\n");
526 }
528 set_fb_event = symbol_get(_mali_osk_fb_control_set);
530 if (set_fb_event) {
531 pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", set_fb_event);
533 set_fb_event(0,0);
535 symbol_put(_mali_osk_fb_control_set);
536 } else {
537 printk("gator: mali offline _mali_osk_fb_control_set symbol not found\n");
538 }
540 /* Generic control interface for Mali DDK. */
541 mali_control = symbol_get(_mali_profiling_control);
543 if (mali_control) {
544 pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", set_fb_event);
546 /* Reset the DDK state - disable counter collection */
547 mali_control(SW_EVENTS_ENABLE, 0);
549 mali_control(FBDUMP_CONTROL_ENABLE, 0);
551 symbol_put(_mali_profiling_control);
552 } else {
553 printk("gator: mali offline _mali_profiling_control symbol not found\n");
554 }
556 if (_mali_profiling_get_counters_function_pointer){
557 symbol_put(_mali_profiling_get_counters);
558 }
560 }
562 static int gator_events_mali_start(void) {
563 // register tracepoints
564 if (GATOR_REGISTER_TRACE(mali_hw_counter)) {
565 printk("gator: mali_hw_counter tracepoint failed to activate\n");
566 return -1;
567 }
569 #if GATOR_MALI_INTERFACE_STYLE == 1
570 /* None. */
571 #elif GATOR_MALI_INTERFACE_STYLE == 2
572 /* For patched Mali driver. */
573 if (GATOR_REGISTER_TRACE(mali_sw_counter)) {
574 printk("gator: mali_sw_counter tracepoint failed to activate\n");
575 return -1;
576 }
577 #elif GATOR_MALI_INTERFACE_STYLE == 3
578 /* For Mali drivers with built-in support. */
579 if (GATOR_REGISTER_TRACE(mali_sw_counters)) {
580 printk("gator: mali_sw_counters tracepoint failed to activate\n");
581 return -1;
582 }
583 #else
584 #error Unknown GATOR_MALI_INTERFACE_STYLE option.
585 #endif
587 trace_registered = 1;
589 mali_counter_initialize();
590 return 0;
591 }
593 static void gator_events_mali_stop(void) {
594 unsigned int cnt;
596 pr_debug("gator: mali stop\n");
598 if (trace_registered) {
599 GATOR_UNREGISTER_TRACE(mali_hw_counter);
601 #if GATOR_MALI_INTERFACE_STYLE == 1
602 /* None. */
603 #elif GATOR_MALI_INTERFACE_STYLE == 2
604 /* For patched Mali driver. */
605 GATOR_UNREGISTER_TRACE(mali_sw_counter);
606 #elif GATOR_MALI_INTERFACE_STYLE == 3
607 /* For Mali drivers with built-in support. */
608 GATOR_UNREGISTER_TRACE(mali_sw_counters);
609 #else
610 #error Unknown GATOR_MALI_INTERFACE_STYLE option.
611 #endif
613 pr_debug("gator: mali timeline tracepoint deactivated\n");
615 trace_registered = 0;
616 }
618 for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) {
619 counter_enabled[cnt] = 0;
620 counter_event[cnt] = 0;
621 counter_address[cnt] = NULL;
622 }
624 mali_counter_deinitialize();
625 }
627 static int gator_events_mali_read(int **buffer) {
628 int cnt, len = 0;
630 if (smp_processor_id()) return 0;
632 // Read the L2 C0 and C1 here.
633 if (counter_enabled[COUNTER_L2_C0] || counter_enabled[COUNTER_L2_C1] ) {
634 u32 src0 = 0;
635 u32 val0 = 0;
636 u32 src1 = 0;
637 u32 val1 = 0;
639 // Poke the driver to get the counter values
640 if (_mali_profiling_get_counters_function_pointer){
641 _mali_profiling_get_counters_function_pointer(&src0, &val0, &src1, &val1);
642 }
644 if (counter_enabled[COUNTER_L2_C0])
645 {
646 // Calculate and save src0's counter val0
647 counter_dump[len++] = counter_key[COUNTER_L2_C0];
648 counter_dump[len++] = get_difference(val0, counter_prev[COUNTER_L2_C0]);
649 }
651 if (counter_enabled[COUNTER_L2_C1])
652 {
653 // Calculate and save src1's counter val1
654 counter_dump[len++] = counter_key[COUNTER_L2_C1];
655 counter_dump[len++] = get_difference(val1, counter_prev[COUNTER_L2_C1]);
656 }
658 // Save the previous values for the counters.
659 counter_prev[COUNTER_L2_C0] = val0;
660 counter_prev[COUNTER_L2_C1] = val1;
661 }
663 // Process other (non-timeline) counters.
664 for (cnt = COUNTER_VP_C0; cnt <= LAST_SW_COUNTER; cnt++) {
665 if (counter_enabled[cnt]) {
666 counter_dump[len++] = counter_key[cnt];
667 counter_dump[len++] = counter_data[cnt];
669 counter_data[cnt] = 0;
670 }
671 }
673 if (buffer) {
674 *buffer = (int*) counter_dump;
675 }
677 return len;
678 }
680 static struct gator_interface gator_events_mali_interface = {
681 .create_files = gator_events_mali_create_files,
682 .start = gator_events_mali_start,
683 .stop = gator_events_mali_stop,
684 .read = gator_events_mali_read,
685 };
687 int gator_events_mali_init(void)
688 {
689 unsigned int cnt;
690 u32 id = gator_mali_get_id();
692 switch (id) {
693 case MALI_T6xx:
694 mali_name = "Mali-T6xx";
695 break;
696 case MALI_400:
697 mali_name = "Mali-400";
698 break;
699 case MALI_300:
700 mali_name = "Mali-300";
701 break;
702 case MALI_200:
703 mali_name = "Mali-200";
704 break;
705 default:
706 printk("Unknown Mali ID (%d)\n", id);
707 return -1;
708 }
710 pr_debug("gator: mali init\n");
712 for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) {
713 counter_enabled[cnt] = 0;
714 counter_event[cnt] = 0;
715 counter_key[cnt] = gator_events_get_key();
716 counter_address[cnt] = NULL;
717 counter_data[cnt] = 0;
718 }
720 trace_registered = 0;
722 return gator_events_install(&gator_events_mali_interface);
723 }
724 gator_events_init(gator_events_mali_init);