gator-driver: Default GATOR_MALI_INTERFACE_STYLE to '2'
[android-sdk/arm-ds5-gator.git] / driver / gator_events_mali.c
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 #if !defined(GATOR_MALI_INTERFACE_STYLE)
18 /*
19  * At the moment, we only have users with the old style interface, so
20  * make our life easier by making it the default...
21  */
22 #define GATOR_MALI_INTERFACE_STYLE (2)
23 #endif
25 /*
26  * There are (currently) three different variants of the comms between gator and Mali:
27  * 1 (deprecated): No software counter support
28  * 2 (deprecated): Tracepoint called for each separate s/w counter value as it appears
29  * 3 (default): Single tracepoint for all s/w counters in a bundle.
30  * Interface style 3 is the default if no other is specified.  1 and 2 will be eliminated when
31  * existing Mali DDKs are upgraded.
32  */
34 #if !defined(GATOR_MALI_INTERFACE_STYLE)
35 #define GATOR_MALI_INTERFACE_STYLE (3)
36 #endif
38 #define MALI_200     (0x0a07)
39 #define MALI_300     (0x0b06) //This is not actually true; Mali-300 is also 0x0b07
40 #define MALI_400     (0x0b07)
41 #define MALI_T6xx    (0x0056)
43 /*
44  * List of possible actions allowing DDK to be controlled by Streamline.
45  * The following numbers are used by DDK to control the frame buffer dumping.
46  */
47 #define FBDUMP_CONTROL_ENABLE (1)
48 #define FBDUMP_CONTROL_RATE (2)
49 #define SW_EVENTS_ENABLE      (3)
50 #define FBDUMP_CONTROL_RESIZE_FACTOR (4)
52 /*
53  * Check that the MALI_SUPPORT define is set to one of the allowable device codes.
54  */
55 #if !defined(MALI_SUPPORT)
56 #error MALI_SUPPORT not defined!
57 #elif (MALI_SUPPORT != MALI_200) && (MALI_SUPPORT != MALI_300) && (MALI_SUPPORT != MALI_400) && (MALI_SUPPORT != MALI_T6xx)
58 #error MALI_SUPPORT set to an invalid device code
59 #endif
61 static const char *mali_name;
63 enum counters {
64     /* Timeline activity */
65     ACTIVITY_VP = 0,
66     ACTIVITY_FP0,
67     ACTIVITY_FP1,
68     ACTIVITY_FP2,
69     ACTIVITY_FP3,
70     
71     /* L2 cache counters */
72     COUNTER_L2_C0,
73     COUNTER_L2_C1,
75     /* Vertex processor counters */
76     COUNTER_VP_C0,
77     COUNTER_VP_C1, 
79     /* Fragment processor counters */
80     COUNTER_FP0_C0,    
81     COUNTER_FP0_C1,     
82     COUNTER_FP1_C0,
83     COUNTER_FP1_C1,
84     COUNTER_FP2_C0,
85     COUNTER_FP2_C1,
86     COUNTER_FP3_C0,
87     COUNTER_FP3_C1,
89     /* EGL Software Counters */
90     COUNTER_EGL_BLIT_TIME,
92     /* GLES Software Counters */
93     COUNTER_GLES_DRAW_ELEMENTS_CALLS,
94     COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES,
95     COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED,
96     COUNTER_GLES_DRAW_ARRAYS_CALLS,
97     COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED,
98     COUNTER_GLES_DRAW_POINTS,
99     COUNTER_GLES_DRAW_LINES,
100     COUNTER_GLES_DRAW_LINE_LOOP,
101     COUNTER_GLES_DRAW_LINE_STRIP,
102     COUNTER_GLES_DRAW_TRIANGLES,
103     COUNTER_GLES_DRAW_TRIANGLE_STRIP,
104     COUNTER_GLES_DRAW_TRIANGLE_FAN,
105     COUNTER_GLES_NON_VBO_DATA_COPY_TIME,
106     COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI,
107     COUNTER_GLES_UPLOAD_TEXTURE_TIME,
108     COUNTER_GLES_UPLOAD_VBO_TIME,
109     COUNTER_GLES_NUM_FLUSHES,
110     COUNTER_GLES_NUM_VSHADERS_GENERATED,
111     COUNTER_GLES_NUM_FSHADERS_GENERATED,
112     COUNTER_GLES_VSHADER_GEN_TIME,
113     COUNTER_GLES_FSHADER_GEN_TIME,
114     COUNTER_GLES_INPUT_TRIANGLES,
115     COUNTER_GLES_VXCACHE_HIT,
116     COUNTER_GLES_VXCACHE_MISS,
117     COUNTER_GLES_VXCACHE_COLLISION,
118     COUNTER_GLES_CULLED_TRIANGLES,
119     COUNTER_GLES_CULLED_LINES,
120     COUNTER_GLES_BACKFACE_TRIANGLES,
121     COUNTER_GLES_GBCLIP_TRIANGLES,
122     COUNTER_GLES_GBCLIP_LINES,
123     COUNTER_GLES_TRIANGLES_DRAWN,
124     COUNTER_GLES_DRAWCALL_TIME,
125     COUNTER_GLES_TRIANGLES_COUNT,
126     COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT,
127     COUNTER_GLES_STRIP_TRIANGLES_COUNT,
128     COUNTER_GLES_FAN_TRIANGLES_COUNT,
129     COUNTER_GLES_LINES_COUNT,
130     COUNTER_GLES_INDEPENDENT_LINES_COUNT,
131     COUNTER_GLES_STRIP_LINES_COUNT,
132     COUNTER_GLES_LOOP_LINES_COUNT,
134         COUNTER_FILMSTRIP,
136     NUMBER_OF_EVENTS
137 };
139 #define FIRST_ACTIVITY_EVENT    ACTIVITY_VP
140 #define LAST_ACTIVITY_EVENT     ACTIVITY_FP3
142 #define FIRST_HW_COUNTER        COUNTER_L2_C0
143 #define LAST_HW_COUNTER         COUNTER_FP3_C1
145 #define FIRST_SW_COUNTER        COUNTER_EGL_BLIT_TIME
146 #define LAST_SW_COUNTER         COUNTER_GLES_LOOP_LINES_COUNT
148 #define FIRST_SPECIAL_COUNTER   COUNTER_FILMSTRIP
149 #define LAST_SPECIAL_COUNTER    COUNTER_FILMSTRIP
151 /* gatorfs variables for counter enable state,
152  * the event the counter should count and the
153  * 'key' (a unique id set by gatord and returned
154  * by gator.ko)
155  */
156 static unsigned long counter_enabled[NUMBER_OF_EVENTS];
157 static unsigned long counter_event[NUMBER_OF_EVENTS];
158 static unsigned long counter_key[NUMBER_OF_EVENTS];
160 /* The data we have recorded */
161 static u32 counter_data[NUMBER_OF_EVENTS];
162 /* The address to sample (or 0 if samples are sent to us) */
163 static u32* counter_address[NUMBER_OF_EVENTS];
165 /* An array used to return the data we recorded
166  * as key,value pairs hence the *2
167  */
168 static unsigned long counter_dump[NUMBER_OF_EVENTS * 2];
169 static unsigned long counter_prev[NUMBER_OF_EVENTS];
171 /* Note whether tracepoints have been registered */
172 static int trace_registered;
174 /**
175  * Calculate the difference and handle the overflow.
176  */
177 static u32 get_difference(u32 start, u32 end)
179         if (start - end >= 0)
180         {
181                 return start - end;
182         }
184         // Mali counters are unsigned 32 bit values that wrap.
185         return (4294967295u - end) + start;
188 /**
189  * Returns non-zero if the given counter ID is an activity counter.
190  */
191 static inline int is_activity_counter(unsigned int event_id)
193     return (event_id >= FIRST_ACTIVITY_EVENT && 
194         event_id <= LAST_ACTIVITY_EVENT);
197 /**
198  * Returns non-zero if the given counter ID is a hardware counter.
199  */
200 static inline int is_hw_counter(unsigned int event_id)
202     return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER);
205 /**
206  * Returns non-zero if the given counter ID is a software counter.
207  */
208 static inline int is_sw_counter(unsigned int event_id)
210     return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER);
213 /*
214  * The Mali DDK uses s64 types to contain software counter values, but gator
215  * can only use a maximum of 32 bits. This function scales a software counter
216  * to an appopriate range.
217  */
218 static u32 scale_sw_counter_value(unsigned int event_id, signed long long value)
220     u32 scaled_value;
222     switch (event_id) {
223         case COUNTER_GLES_UPLOAD_TEXTURE_TIME:
224         case COUNTER_GLES_UPLOAD_VBO_TIME:
225             scaled_value = (u32)div_s64(value, 1000000);
226             break;
227         default:
228             scaled_value = (u32)value;
229             break;
230     }
232     return scaled_value;
235 /* Probe for continuously sampled counter */
236 #if 0 //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING
237 GATOR_DEFINE_PROBE(mali_sample_address, TP_PROTO(unsigned int event_id, u32* addr))
239     /* Turning on too many pr_debug statements in frequently called functions
240      * can cause stability and/or performance problems
241      */
242     //pr_debug("gator: mali_sample_address %d %d\n", event_id, addr);
243     if (event_id >= ACTIVITY_VP && event_id <= COUNTER_FP3_C1) {
244         counter_address[event_id] = addr;
245     }
247 #endif
249 /* Probe for hardware counter events */
250 GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int value))
252     /* Turning on too many pr_debug statements in frequently called functions
253      * can cause stability and/or performance problems
254      */
255     //pr_debug("gator: mali_hw_counter %d %d\n", event_id, value);
256     if (is_hw_counter(event_id)) {
257         counter_data[event_id] = value;
258     }
261 #if GATOR_MALI_INTERFACE_STYLE == 2
262 GATOR_DEFINE_PROBE(mali_sw_counter, TP_PROTO(unsigned int event_id, signed long long value))
264     if (is_sw_counter(event_id)) {
265         counter_data[event_id] = scale_sw_counter_value(event_id, value);
266     }
268 #endif /* GATOR_MALI_INTERFACE_STYLE == 2 */
271 #if GATOR_MALI_INTERFACE_STYLE == 3
272 GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void * surface_id, unsigned int * counters))
274         u32 i;
276         /* Copy over the values for those counters which are enabled. */
277         for(i=FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++)
278         {
279                 if(counter_enabled[i])
280                 {
281                         counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]);
282                 }
283         }
285 #endif /* GATOR_MALI_INTERFACE_STYLE == 3 */
287 //TODO need to work out how many fp units we have
288 u32 gator_mali_get_n_fp(void) {
289     return 4;
292 //TODO need to work out what kind of Mali we are looking at
293 u32 gator_mali_get_id(void) {
294     return MALI_SUPPORT;
297 int gator_events_mali_create_files(struct super_block *sb, struct dentry *root) {
298     struct dentry *dir;
299     int event;
300     int n_fp = gator_mali_get_n_fp();
302     /*
303      * Create the filesystem entries for vertex processor, fragement processor
304      * and L2 cache timeline and hardware counters. Software counters get 
305      * special handling after this block.
306      */
307     for (event = FIRST_ACTIVITY_EVENT; event <= LAST_HW_COUNTER; event++)
308     {
309         char buf[40];
311         /* 
312          * We can skip this event if it's for a non-existent fragment
313          * processor.
314          */
315         if (((event - ACTIVITY_FP0 >= n_fp) && (event < COUNTER_L2_C0)) ||
316             (((event - COUNTER_FP0_C0)/2 >= n_fp)))
317         {
318             continue;
319         }
321         /* Otherwise, set up the filesystem entry for this event. */
322         switch (event) {
323             case ACTIVITY_VP:
324                 snprintf(buf, sizeof buf, "ARM_%s_VP_active", mali_name);
325                 break;
326             case ACTIVITY_FP0:
327             case ACTIVITY_FP1:
328             case ACTIVITY_FP2:
329             case ACTIVITY_FP3:
330                 snprintf(buf, sizeof buf, "ARM_%s_FP%d_active", 
331                     mali_name, event - ACTIVITY_FP0);
332                 break;
333             case COUNTER_L2_C0:
334             case COUNTER_L2_C1:
335                 snprintf(buf, sizeof buf, "ARM_%s_L2_cnt%d", 
336                     mali_name, event - COUNTER_L2_C0);
337                 break;
338             case COUNTER_VP_C0:
339             case COUNTER_VP_C1:
340                 snprintf(buf, sizeof buf, "ARM_%s_VP_cnt%d", 
341                     mali_name, event - COUNTER_VP_C0);
342                 break;
343             case COUNTER_FP0_C0:
344             case COUNTER_FP0_C1:
345             case COUNTER_FP1_C0:
346             case COUNTER_FP1_C1:
347             case COUNTER_FP2_C0:
348             case COUNTER_FP2_C1:
349             case COUNTER_FP3_C0:
350             case COUNTER_FP3_C1:
351                 snprintf(buf, sizeof buf, "ARM_%s_FP%d_cnt%d", mali_name, 
352                     (event - COUNTER_FP0_C0) / 2, (event - COUNTER_FP0_C0) % 2);
353                 break;
354             default:
355                 printk("gator: trying to create file for non-existent counter (%d)\n", event);
356                 continue;
357         }
359         dir = gatorfs_mkdir(sb, root, buf);
360         
361         if (!dir) {
362             return -1;
363         }
364         
365         gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
366         
367         /* Only create an event node for counters that can change what they count */
368         if (event >= COUNTER_L2_C0) {
369             gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
370         }
371         
372         gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
373     }
375     /* Now set up the software counter entries */
376     for (event = FIRST_SW_COUNTER; event <= LAST_SW_COUNTER; event++)
377     {
378         char buf[40];
380         snprintf(buf, sizeof(buf), "ARM_%s_SW_%d", mali_name, event);
382         dir = gatorfs_mkdir(sb, root, buf);
384         if (!dir) {
385             return -1;
386         }
388         gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
389         gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
390     }
392         /* Now set up the special counter entries */
393     for (event = FIRST_SPECIAL_COUNTER; event <= LAST_SPECIAL_COUNTER; event++)
394     {
395         char buf[40];
397         snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip", mali_name);
399         dir = gatorfs_mkdir(sb, root, buf);
401         if (!dir) {
402             return -1;
403         }
405         gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
406         gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
407         gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
408     }
411     return 0;
414 //TODO
415 void _mali_profiling_set_event(unsigned int, unsigned int);
416 void _mali_osk_fb_control_set(unsigned int, unsigned int);
417 void _mali_profiling_control(unsigned int, unsigned int);
419 void _mali_profiling_get_counters(unsigned int*, unsigned int*, unsigned int*, unsigned int*);
420 void (*_mali_profiling_get_counters_function_pointer)(unsigned int*, unsigned int*, unsigned int*, unsigned int*);
422 /*
423  * Examine list of software counters and determine if any one is enabled.
424  * Returns 1 if any counter is enabled, 0 if none is.
425  */
426 static int is_any_sw_counter_enabled(void)
428         unsigned int i;
430         for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++)
431         {
432                 if (counter_enabled[i])
433                 {
434                         return 1;       /* At least one counter is enabled */
435                 }
436         }
438         return 0;       /* No s/w counters enabled */
441 static void mali_counter_initialize(void) 
443     /* If a Mali driver is present and exporting the appropriate symbol
444      * then we can request the HW counters (of which there are only 2)
445      * be configured to count the desired events
446      */
447     void (*set_hw_event)(unsigned int, unsigned int);
448         void (*set_fb_event)(unsigned int, unsigned int);
449         void (*mali_control)(unsigned int, unsigned int);
451     set_hw_event = symbol_get(_mali_profiling_set_event);
453     if (set_hw_event) {
454         int i;
456         pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n",set_hw_event);
458         for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
459             if (counter_enabled[i]) {
460                 set_hw_event(i, counter_event[i]);
461             } else {
462                 set_hw_event(i, 0xFFFFFFFF);
463             }
464         }
466         symbol_put(_mali_profiling_set_event);
467     } else {
468         printk("gator: mali online _mali_profiling_set_event symbol not found\n");
469     }
471         set_fb_event = symbol_get(_mali_osk_fb_control_set);
473         if (set_fb_event) {
474                 pr_debug("gator: mali online _mali_osk_fb_control_set symbol @ %p\n", set_fb_event);
476         set_fb_event(0,(counter_enabled[COUNTER_FILMSTRIP]?1:0));
478                 symbol_put(_mali_osk_fb_control_set);
479         } else {
480                 printk("gator: mali online _mali_osk_fb_control_set symbol not found\n");
481         }
483         /* Generic control interface for Mali DDK. */
484         mali_control = symbol_get(_mali_profiling_control);
485         if (mali_control) {
486                 /* The event attribute in the XML file keeps the actual frame rate. */
487                 unsigned int rate = counter_event[COUNTER_FILMSTRIP] & 0xff;
488                 unsigned int resize_factor = (counter_event[COUNTER_FILMSTRIP] >> 8) & 0xff;
490                 pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control);
492                 mali_control(SW_EVENTS_ENABLE, (is_any_sw_counter_enabled()?1:0));
493                 mali_control(FBDUMP_CONTROL_ENABLE, (counter_enabled[COUNTER_FILMSTRIP]?1:0));
494                 mali_control(FBDUMP_CONTROL_RATE, rate);
495                 mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor);
497                 pr_debug("gator: sent mali_control enabled=%d, rate=%d\n", (counter_enabled[COUNTER_FILMSTRIP]?1:0), rate);
499                 symbol_put(_mali_profiling_control);
500         } else {
501                 printk("gator: mali online _mali_profiling_control symbol not found\n");
502         }
504         _mali_profiling_get_counters_function_pointer =  symbol_get(_mali_profiling_get_counters);
505         if (_mali_profiling_get_counters_function_pointer){
506                 pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", _mali_profiling_get_counters_function_pointer);
507                 counter_prev[COUNTER_L2_C0] = 0;
508                 counter_prev[COUNTER_L2_C1] = 0;
509         }
510         else{
511                 pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol  not defined");
512         }
515 static void mali_counter_deinitialize(void) 
517     void (*set_hw_event)(unsigned int, unsigned int);
518         void (*set_fb_event)(unsigned int, unsigned int);
519         void (*mali_control)(unsigned int, unsigned int);
521     set_hw_event = symbol_get(_mali_profiling_set_event);
523     if (set_hw_event) {
524         int i;
525         
526         pr_debug("gator: mali offline _mali_profiling_set_event symbol @ %p\n",set_hw_event);
527         for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
528             set_hw_event(i, 0xFFFFFFFF);
529         }
530         
531         symbol_put(_mali_profiling_set_event);
532     } else {
533         printk("gator: mali offline _mali_profiling_set_event symbol not found\n");
534     }
536         set_fb_event = symbol_get(_mali_osk_fb_control_set);
538         if (set_fb_event) {
539                 pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", set_fb_event);
541         set_fb_event(0,0);
543                 symbol_put(_mali_osk_fb_control_set);
544         } else {
545                 printk("gator: mali offline _mali_osk_fb_control_set symbol not found\n");
546         }
547         
548         /* Generic control interface for Mali DDK. */
549         mali_control = symbol_get(_mali_profiling_control);
551         if (mali_control) {
552                 pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", set_fb_event);
554                 /* Reset the DDK state - disable counter collection */
555                 mali_control(SW_EVENTS_ENABLE, 0);
557                 mali_control(FBDUMP_CONTROL_ENABLE, 0);
559                 symbol_put(_mali_profiling_control);
560         } else {
561                 printk("gator: mali offline _mali_profiling_control symbol not found\n");
562         }
564         if (_mali_profiling_get_counters_function_pointer){
565                 symbol_put(_mali_profiling_get_counters);
566         }
570 static int gator_events_mali_start(void) {
571     // register tracepoints
572     if (GATOR_REGISTER_TRACE(mali_hw_counter)) {
573         printk("gator: mali_hw_counter tracepoint failed to activate\n");
574         return -1;
575     }
577 #if GATOR_MALI_INTERFACE_STYLE == 1
578                 /* None. */
579 #elif GATOR_MALI_INTERFACE_STYLE == 2
580                 /* For patched Mali driver. */
581     if (GATOR_REGISTER_TRACE(mali_sw_counter)) {
582         printk("gator: mali_sw_counter tracepoint failed to activate\n");
583         return -1;
584     }
585 #elif GATOR_MALI_INTERFACE_STYLE == 3
586 /* For Mali drivers with built-in support. */
587     if (GATOR_REGISTER_TRACE(mali_sw_counters)) {
588         printk("gator: mali_sw_counters tracepoint failed to activate\n");
589         return -1;
590     }
591 #else
592 #error Unknown GATOR_MALI_INTERFACE_STYLE option.
593 #endif
595     trace_registered = 1;
597     mali_counter_initialize();
598     return 0;
601 static void gator_events_mali_stop(void) {
602     unsigned int cnt;
604     pr_debug("gator: mali stop\n");
606     if (trace_registered) {
607         GATOR_UNREGISTER_TRACE(mali_hw_counter);
609 #if GATOR_MALI_INTERFACE_STYLE == 1
610     /* None. */
611 #elif GATOR_MALI_INTERFACE_STYLE == 2
612     /* For patched Mali driver. */
613     GATOR_UNREGISTER_TRACE(mali_sw_counter);
614 #elif GATOR_MALI_INTERFACE_STYLE == 3
615     /* For Mali drivers with built-in support. */
616     GATOR_UNREGISTER_TRACE(mali_sw_counters);
617 #else
618 #error Unknown GATOR_MALI_INTERFACE_STYLE option.
619 #endif
621         pr_debug("gator: mali timeline tracepoint deactivated\n");
622         
623         trace_registered = 0;
624     }
626     for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) {
627         counter_enabled[cnt] = 0;
628         counter_event[cnt] = 0;
629         counter_address[cnt] = NULL;
630     }
632     mali_counter_deinitialize();
635 static int gator_events_mali_read(int **buffer) {
636     int cnt, len = 0;
638     if (smp_processor_id()) return 0;
640     // Read the L2 C0 and C1 here.
641     if (counter_enabled[COUNTER_L2_C0] || counter_enabled[COUNTER_L2_C1] ) {
642         u32 src0 = 0;
643         u32 val0 = 0;
644         u32 src1 = 0;
645         u32 val1 = 0;
647         // Poke the driver to get the counter values
648         if (_mali_profiling_get_counters_function_pointer){
649             _mali_profiling_get_counters_function_pointer(&src0, &val0, &src1, &val1);
650         }
652         if (counter_enabled[COUNTER_L2_C0])
653         {
654             // Calculate and save src0's counter val0
655             counter_dump[len++] = counter_key[COUNTER_L2_C0];
656             counter_dump[len++] = get_difference(val0, counter_prev[COUNTER_L2_C0]);
657         }
659         if (counter_enabled[COUNTER_L2_C1])
660         {
661             // Calculate and save src1's counter val1
662             counter_dump[len++] = counter_key[COUNTER_L2_C1];
663             counter_dump[len++] = get_difference(val1, counter_prev[COUNTER_L2_C1]);
664         }
666         // Save the previous values for the counters.
667         counter_prev[COUNTER_L2_C0] = val0;
668         counter_prev[COUNTER_L2_C1] = val1;
669     }
671     // Process other (non-timeline) counters.
672     for (cnt = COUNTER_VP_C0; cnt <= LAST_SW_COUNTER; cnt++) {
673         if (counter_enabled[cnt]) {
674             counter_dump[len++] = counter_key[cnt];
675             counter_dump[len++] = counter_data[cnt];
677             counter_data[cnt] = 0;
678         }
679     }
681     if (buffer) {
682         *buffer = (int*) counter_dump;
683     }
685     return len;
688 static struct gator_interface gator_events_mali_interface = {
689     .create_files = gator_events_mali_create_files,
690     .start = gator_events_mali_start,
691     .stop = gator_events_mali_stop,
692     .read = gator_events_mali_read,
693 };
695 int gator_events_mali_init(void)
697     unsigned int cnt;
698     u32 id = gator_mali_get_id();
700     switch (id) {
701     case MALI_T6xx:
702         mali_name = "Mali-T6xx";
703         break;
704     case MALI_400:
705         mali_name = "Mali-400";
706         break;
707     case MALI_300:
708         mali_name = "Mali-300";
709         break;
710     case MALI_200:
711         mali_name = "Mali-200";
712         break;
713     default:
714         printk("Unknown Mali ID (%d)\n", id);
715         return -1;
716     }
718     pr_debug("gator: mali init\n");
720     for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) {
721         counter_enabled[cnt] = 0;
722         counter_event[cnt] = 0;
723         counter_key[cnt] = gator_events_get_key();
724         counter_address[cnt] = NULL;
725                 counter_data[cnt] = 0;
726     }
728     trace_registered = 0;
730     return gator_events_install(&gator_events_mali_interface);
732 gator_events_init(gator_events_mali_init);