gator-driver: Default GATOR_MALI_INTERFACE_STYLE to '2'
[android-sdk/arm-ds5-gator.git] / driver / gator_events_mali_400.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 #include "gator_events_mali_common.h"
18 #include "gator_events_mali_400.h"
20 #if !defined(GATOR_MALI_INTERFACE_STYLE)
21 /*
22  * At the moment, we only have users with the old style interface, so
23  * make our life easier by making it the default...
24  */
25 #define GATOR_MALI_INTERFACE_STYLE (2)
26 #endif
28 /*
29  * There are (currently) three different variants of the comms between gator and Mali:
30  * 1 (deprecated): No software counter support
31  * 2 (deprecated): Tracepoint called for each separate s/w counter value as it appears
32  * 3 (default): Single tracepoint for all s/w counters in a bundle.
33  * Interface style 3 is the default if no other is specified.  1 and 2 will be eliminated when
34  * existing Mali DDKs are upgraded.
35  */
37 #if !defined(GATOR_MALI_INTERFACE_STYLE)
38 #define GATOR_MALI_INTERFACE_STYLE (3)
39 #endif
41 /*
42  * List of possible actions allowing DDK to be controlled by Streamline.
43  * The following numbers are used by DDK to control the frame buffer dumping.
44  */
45 #define FBDUMP_CONTROL_ENABLE (1)
46 #define FBDUMP_CONTROL_RATE (2)
47 #define SW_EVENTS_ENABLE      (3)
48 #define FBDUMP_CONTROL_RESIZE_FACTOR (4)
50 /*
51  * Check that the MALI_SUPPORT define is set to one of the allowable device codes.
52  */
53 #if (MALI_SUPPORT != MALI_400)
54 #error MALI_SUPPORT set to an invalid device code: expecting MALI_400
55 #endif
57 /*
58  * The number of fragment processors.  Update to suit your hardware implementation.
59  */
60 #define NUM_FP_UNITS            (4)
62 enum counters {
63         /* Timeline activity */
64         ACTIVITY_VP = 0,
65         ACTIVITY_FP0,
66         ACTIVITY_FP1,
67         ACTIVITY_FP2,
68         ACTIVITY_FP3,
70         /* L2 cache counters */
71         COUNTER_L2_C0,
72         COUNTER_L2_C1,
74         /* Vertex processor counters */
75         COUNTER_VP_C0,
76         COUNTER_VP_C1,
78         /* Fragment processor counters */
79         COUNTER_FP0_C0,
80         COUNTER_FP0_C1,
81         COUNTER_FP1_C0,
82         COUNTER_FP1_C1,
83         COUNTER_FP2_C0,
84         COUNTER_FP2_C1,
85         COUNTER_FP3_C0,
86         COUNTER_FP3_C1,
88         /* EGL Software Counters */
89         COUNTER_EGL_BLIT_TIME,
91         /* GLES Software Counters */
92         COUNTER_GLES_DRAW_ELEMENTS_CALLS,
93         COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES,
94         COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED,
95         COUNTER_GLES_DRAW_ARRAYS_CALLS,
96         COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED,
97         COUNTER_GLES_DRAW_POINTS,
98         COUNTER_GLES_DRAW_LINES,
99         COUNTER_GLES_DRAW_LINE_LOOP,
100         COUNTER_GLES_DRAW_LINE_STRIP,
101         COUNTER_GLES_DRAW_TRIANGLES,
102         COUNTER_GLES_DRAW_TRIANGLE_STRIP,
103         COUNTER_GLES_DRAW_TRIANGLE_FAN,
104         COUNTER_GLES_NON_VBO_DATA_COPY_TIME,
105         COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI,
106         COUNTER_GLES_UPLOAD_TEXTURE_TIME,
107         COUNTER_GLES_UPLOAD_VBO_TIME,
108         COUNTER_GLES_NUM_FLUSHES,
109         COUNTER_GLES_NUM_VSHADERS_GENERATED,
110         COUNTER_GLES_NUM_FSHADERS_GENERATED,
111         COUNTER_GLES_VSHADER_GEN_TIME,
112         COUNTER_GLES_FSHADER_GEN_TIME,
113         COUNTER_GLES_INPUT_TRIANGLES,
114         COUNTER_GLES_VXCACHE_HIT,
115         COUNTER_GLES_VXCACHE_MISS,
116         COUNTER_GLES_VXCACHE_COLLISION,
117         COUNTER_GLES_CULLED_TRIANGLES,
118         COUNTER_GLES_CULLED_LINES,
119         COUNTER_GLES_BACKFACE_TRIANGLES,
120         COUNTER_GLES_GBCLIP_TRIANGLES,
121         COUNTER_GLES_GBCLIP_LINES,
122         COUNTER_GLES_TRIANGLES_DRAWN,
123         COUNTER_GLES_DRAWCALL_TIME,
124         COUNTER_GLES_TRIANGLES_COUNT,
125         COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT,
126         COUNTER_GLES_STRIP_TRIANGLES_COUNT,
127         COUNTER_GLES_FAN_TRIANGLES_COUNT,
128         COUNTER_GLES_LINES_COUNT,
129         COUNTER_GLES_INDEPENDENT_LINES_COUNT,
130         COUNTER_GLES_STRIP_LINES_COUNT,
131         COUNTER_GLES_LOOP_LINES_COUNT,
133         COUNTER_FILMSTRIP,
134         COUNTER_FREQUENCY,
135         COUNTER_VOLTAGE,
137         NUMBER_OF_EVENTS
138 };
140 #define FIRST_ACTIVITY_EVENT    ACTIVITY_VP
141 #define LAST_ACTIVITY_EVENT     ACTIVITY_FP3
143 #define FIRST_HW_COUNTER        COUNTER_L2_C0
144 #define LAST_HW_COUNTER         COUNTER_FP3_C1
146 #define FIRST_SW_COUNTER        COUNTER_EGL_BLIT_TIME
147 #define LAST_SW_COUNTER         COUNTER_GLES_LOOP_LINES_COUNT
149 #define FIRST_SPECIAL_COUNTER   COUNTER_FILMSTRIP
150 #define LAST_SPECIAL_COUNTER    COUNTER_VOLTAGE
152 /* gatorfs variables for counter enable state,
153  * the event the counter should count and the
154  * 'key' (a unique id set by gatord and returned
155  * by gator.ko)
156  */
157 static unsigned long counter_enabled[NUMBER_OF_EVENTS];
158 static unsigned long counter_event[NUMBER_OF_EVENTS];
159 static unsigned long counter_key[NUMBER_OF_EVENTS];
161 /* The data we have recorded */
162 static u32 counter_data[NUMBER_OF_EVENTS];
163 /* The address to sample (or 0 if samples are sent to us) */
164 static u32 *counter_address[NUMBER_OF_EVENTS];
166 /* An array used to return the data we recorded
167  * as key,value pairs hence the *2
168  */
169 static unsigned long counter_dump[NUMBER_OF_EVENTS * 2];
170 static unsigned long counter_prev[NUMBER_OF_EVENTS];
172 /* Note whether tracepoints have been registered */
173 static int trace_registered;
175 /**
176  * Calculate the difference and handle the overflow.
177  */
178 static u32 get_difference(u32 start, u32 end)
180         if (start - end >= 0) {
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 #if GATOR_MALI_INTERFACE_STYLE == 2
206 /**
207  * Returns non-zero if the given counter ID is a software counter.
208  */
209 static inline int is_sw_counter(unsigned int event_id)
211         return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER);
213 #endif
215 #if GATOR_MALI_INTERFACE_STYLE == 2
216 /*
217  * The Mali DDK uses s64 types to contain software counter values, but gator
218  * can only use a maximum of 32 bits. This function scales a software counter
219  * to an appropriate range.
220  */
221 static u32 scale_sw_counter_value(unsigned int event_id, signed long long value)
223         u32 scaled_value;
225         switch (event_id) {
226         case COUNTER_GLES_UPLOAD_TEXTURE_TIME:
227         case COUNTER_GLES_UPLOAD_VBO_TIME:
228                 scaled_value = (u32)div_s64(value, 1000000);
229                 break;
230         default:
231                 scaled_value = (u32)value;
232                 break;
233         }
235         return scaled_value;
237 #endif
239 /* Probe for continuously sampled counter */
240 #if 0                           //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING
241 GATOR_DEFINE_PROBE(mali_sample_address, TP_PROTO(unsigned int event_id, u32 *addr))
243         /* Turning on too many pr_debug statements in frequently called functions
244          * can cause stability and/or performance problems
245          */
246         //pr_debug("gator: mali_sample_address %d %d\n", event_id, addr);
247         if (event_id >= ACTIVITY_VP && event_id <= COUNTER_FP3_C1) {
248                 counter_address[event_id] = addr;
249         }
251 #endif
253 /* Probe for hardware counter events */
254 GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int value))
256         /* Turning on too many pr_debug statements in frequently called functions
257          * can cause stability and/or performance problems
258          */
259         //pr_debug("gator: mali_hw_counter %d %d\n", event_id, value);
260         if (is_hw_counter(event_id)) {
261                 counter_data[event_id] = value;
262         }
265 #if GATOR_MALI_INTERFACE_STYLE == 2
266 GATOR_DEFINE_PROBE(mali_sw_counter, TP_PROTO(unsigned int event_id, signed long long value))
268         if (is_sw_counter(event_id)) {
269                 counter_data[event_id] = scale_sw_counter_value(event_id, value);
270         }
272 #endif /* GATOR_MALI_INTERFACE_STYLE == 2 */
274 #if GATOR_MALI_INTERFACE_STYLE == 3
275 GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surface_id, unsigned int *counters))
277         u32 i;
279         /* Copy over the values for those counters which are enabled. */
280         for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) {
281                 if (counter_enabled[i]) {
282                         counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]);
283                 }
284         }
286 #endif /* GATOR_MALI_INTERFACE_STYLE == 3 */
288 static int create_files(struct super_block *sb, struct dentry *root)
290         struct dentry *dir;
291         int event;
292         int n_fp = NUM_FP_UNITS;
294         const char *mali_name = gator_mali_get_mali_name();
296         /*
297          * Create the filesystem entries for vertex processor, fragment processor
298          * and L2 cache timeline and hardware counters. Software counters get 
299          * special handling after this block.
300          */
301         for (event = FIRST_ACTIVITY_EVENT; event <= LAST_HW_COUNTER; event++) {
302                 char buf[40];
304                 /* 
305                  * We can skip this event if it's for a non-existent fragment
306                  * processor.
307                  */
308                 if (((event - ACTIVITY_FP0 >= n_fp) && (event < COUNTER_L2_C0))
309                     || (((event - COUNTER_FP0_C0) / 2 >= n_fp))) {
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",
344                                  mali_name, (event - COUNTER_FP0_C0) / 2,
345                                  (event - COUNTER_FP0_C0) % 2);
346                         break;
347                 default:
348                         printk("gator: trying to create file for non-existent counter (%d)\n", event);
349                         continue;
350                 }
352                 dir = gatorfs_mkdir(sb, root, buf);
354                 if (!dir) {
355                         return -1;
356                 }
358                 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
360                 /* Only create an event node for counters that can change what they count */
361                 if (event >= COUNTER_L2_C0) {
362                         gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
363                 }
365                 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
366         }
368         /* Now set up the software counter entries */
369         for (event = FIRST_SW_COUNTER; event <= LAST_SW_COUNTER; event++) {
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                 char buf[40];
388                 switch (event) {
389                 case COUNTER_FILMSTRIP:
390                         snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip_cnt0", mali_name);
391                         break;
393                 case COUNTER_FREQUENCY:
394                         snprintf(buf, sizeof(buf), "ARM_%s_Frequency", mali_name);
395                         break;
397                 case COUNTER_VOLTAGE:
398                         snprintf(buf, sizeof(buf), "ARM_%s_Voltage", mali_name);
399                         break;
401                 default:
402                         break;
403                 }
405                 dir = gatorfs_mkdir(sb, root, buf);
407                 if (!dir) {
408                         return -1;
409                 }
411                 gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
412                 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
413                 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
414         }
416         return 0;
419 /*
420  * Local store for the get_counters entry point into the DDK.
421  * This is stored here since it is used very regularly.
422  */
423 static mali_profiling_get_counters_type *mali_get_counters = NULL;
425 /*
426  * Examine list of software counters and determine if any one is enabled.
427  * Returns 1 if any counter is enabled, 0 if none is.
428  */
429 static int is_any_sw_counter_enabled(void)
431         unsigned int i;
433         for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) {
434                 if (counter_enabled[i]) {
435                         return 1;       /* At least one counter is enabled */
436                 }
437         }
439         return 0;               /* No s/w counters enabled */
442 static void mali_counter_initialize(void)
444         /* If a Mali driver is present and exporting the appropriate symbol
445          * then we can request the HW counters (of which there are only 2)
446          * be configured to count the desired events
447          */
448         mali_profiling_set_event_type *mali_set_hw_event;
449         mali_osk_fb_control_set_type *mali_set_fb_event;
450         mali_profiling_control_type *mali_control;
452         mali_set_hw_event = symbol_get(_mali_profiling_set_event);
454         if (mali_set_hw_event) {
455                 int i;
457                 pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n", mali_set_hw_event);
459                 for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
460                         if (counter_enabled[i]) {
461                                 mali_set_hw_event(i, counter_event[i]);
462                         } else {
463                                 mali_set_hw_event(i, 0xFFFFFFFF);
464                         }
465                 }
467                 symbol_put(_mali_profiling_set_event);
468         } else {
469                 printk("gator: mali online _mali_profiling_set_event symbol not found\n");
470         }
472         mali_set_fb_event = symbol_get(_mali_osk_fb_control_set);
474         if (mali_set_fb_event) {
475                 pr_debug("gator: mali online _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
477                 mali_set_fb_event(0, (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0));
479                 symbol_put(_mali_osk_fb_control_set);
480         } else {
481                 printk("gator: mali online _mali_osk_fb_control_set symbol not found\n");
482         }
484         /* Generic control interface for Mali DDK. */
485         mali_control = symbol_get(_mali_profiling_control);
486         if (mali_control) {
487                 /* The event attribute in the XML file keeps the actual frame rate. */
488                 unsigned int rate = counter_event[COUNTER_FILMSTRIP] & 0xff;
489                 unsigned int resize_factor = (counter_event[COUNTER_FILMSTRIP] >> 8) & 0xff;
491                 pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control);
493                 mali_control(SW_EVENTS_ENABLE, (is_any_sw_counter_enabled() ? 1 : 0));
494                 mali_control(FBDUMP_CONTROL_ENABLE, (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0));
495                 mali_control(FBDUMP_CONTROL_RATE, rate);
496                 mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor);
498                 pr_debug("gator: sent mali_control enabled=%d, rate=%d\n", (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0), rate);
500                 symbol_put(_mali_profiling_control);
501         } else {
502                 printk("gator: mali online _mali_profiling_control symbol not found\n");
503         }
505         mali_get_counters = symbol_get(_mali_profiling_get_counters);
506         if (mali_get_counters) {
507                 pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", mali_get_counters);
508                 counter_prev[COUNTER_L2_C0] = 0;
509                 counter_prev[COUNTER_L2_C1] = 0;
510         } else {
511                 pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined");
512         }
515 static void mali_counter_deinitialize(void)
517         mali_profiling_set_event_type *mali_set_hw_event;
518         mali_osk_fb_control_set_type *mali_set_fb_event;
519         mali_profiling_control_type *mali_control;
521         mali_set_hw_event = symbol_get(_mali_profiling_set_event);
523         if (mali_set_hw_event) {
524                 int i;
526                 pr_debug("gator: mali offline _mali_profiling_set_event symbol @ %p\n", mali_set_hw_event);
527                 for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
528                         mali_set_hw_event(i, 0xFFFFFFFF);
529                 }
531                 symbol_put(_mali_profiling_set_event);
532         } else {
533                 printk("gator: mali offline _mali_profiling_set_event symbol not found\n");
534         }
536         mali_set_fb_event = symbol_get(_mali_osk_fb_control_set);
538         if (mali_set_fb_event) {
539                 pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
541                 mali_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         }
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", mali_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_get_counters) {
565                 symbol_put(_mali_profiling_get_counters);
566         }
570 static int start(void)
572         // register tracepoints
573         if (GATOR_REGISTER_TRACE(mali_hw_counter)) {
574                 printk("gator: mali_hw_counter tracepoint failed to activate\n");
575                 return -1;
576         }
578 #if GATOR_MALI_INTERFACE_STYLE == 1
579         /* None. */
580 #elif GATOR_MALI_INTERFACE_STYLE == 2
581         /* For patched Mali driver. */
582         if (GATOR_REGISTER_TRACE(mali_sw_counter)) {
583                 printk("gator: mali_sw_counter tracepoint failed to activate\n");
584                 return -1;
585         }
586 #elif GATOR_MALI_INTERFACE_STYLE == 3
587 /* For Mali drivers with built-in support. */
588         if (GATOR_REGISTER_TRACE(mali_sw_counters)) {
589                 printk("gator: mali_sw_counters tracepoint failed to activate\n");
590                 return -1;
591         }
592 #else
593 #error Unknown GATOR_MALI_INTERFACE_STYLE option.
594 #endif
596         trace_registered = 1;
598         mali_counter_initialize();
599         return 0;
602 static void stop(void)
604         unsigned int cnt;
606         pr_debug("gator: mali stop\n");
608         if (trace_registered) {
609                 GATOR_UNREGISTER_TRACE(mali_hw_counter);
611 #if GATOR_MALI_INTERFACE_STYLE == 1
612                 /* None. */
613 #elif GATOR_MALI_INTERFACE_STYLE == 2
614                 /* For patched Mali driver. */
615                 GATOR_UNREGISTER_TRACE(mali_sw_counter);
616 #elif GATOR_MALI_INTERFACE_STYLE == 3
617                 /* For Mali drivers with built-in support. */
618                 GATOR_UNREGISTER_TRACE(mali_sw_counters);
619 #else
620 #error Unknown GATOR_MALI_INTERFACE_STYLE option.
621 #endif
623                 pr_debug("gator: mali timeline tracepoint deactivated\n");
625                 trace_registered = 0;
626         }
628         for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) {
629                 counter_enabled[cnt] = 0;
630                 counter_event[cnt] = 0;
631                 counter_address[cnt] = NULL;
632         }
634         mali_counter_deinitialize();
637 static int read(int **buffer)
639         int cnt, len = 0;
641         if (smp_processor_id())
642                 return 0;
644         // Read the L2 C0 and C1 here.
645         if (counter_enabled[COUNTER_L2_C0] || counter_enabled[COUNTER_L2_C1]) {
646                 u32 src0 = 0;
647                 u32 val0 = 0;
648                 u32 src1 = 0;
649                 u32 val1 = 0;
651                 // Poke the driver to get the counter values
652                 if (mali_get_counters) {
653                         mali_get_counters(&src0, &val0, &src1, &val1);
654                 }
656                 if (counter_enabled[COUNTER_L2_C0]) {
657                         // Calculate and save src0's counter val0
658                         counter_dump[len++] = counter_key[COUNTER_L2_C0];
659                         counter_dump[len++] = get_difference(val0, counter_prev[COUNTER_L2_C0]);
660                 }
662                 if (counter_enabled[COUNTER_L2_C1]) {
663                         // Calculate and save src1's counter val1
664                         counter_dump[len++] = counter_key[COUNTER_L2_C1];
665                         counter_dump[len++] = get_difference(val1, counter_prev[COUNTER_L2_C1]);
666                 }
668                 // Save the previous values for the counters.
669                 counter_prev[COUNTER_L2_C0] = val0;
670                 counter_prev[COUNTER_L2_C1] = val1;
671         }
673         // Process other (non-timeline) counters.
674         for (cnt = COUNTER_VP_C0; cnt <= LAST_SW_COUNTER; cnt++) {
675                 if (counter_enabled[cnt]) {
676                         counter_dump[len++] = counter_key[cnt];
677                         counter_dump[len++] = counter_data[cnt];
679                         counter_data[cnt] = 0;
680                 }
681         }
683         /*
684          * Add in the voltage and frequency counters if enabled.  Note that, since these are
685          * actually passed as events, the counter value should not be cleared.
686          */
687         cnt = COUNTER_FREQUENCY;
688         if (counter_enabled[cnt]) {
689                 counter_dump[len++] = counter_key[cnt];
690                 counter_dump[len++] = counter_data[cnt];
691         }
693         cnt = COUNTER_VOLTAGE;
694         if (counter_enabled[cnt]) {
695                 counter_dump[len++] = counter_key[cnt];
696                 counter_dump[len++] = counter_data[cnt];
697         }
699         if (buffer) {
700                 *buffer = (int *)counter_dump;
701         }
703         return len;
706 static struct gator_interface gator_events_mali_interface = {
707         .create_files = create_files,
708         .start = start,
709         .stop = stop,
710         .read = read,
711 };
713 extern void gator_events_mali_log_dvfs_event(unsigned int frequency_mhz, unsigned int voltage_mv)
715         counter_data[COUNTER_FREQUENCY] = frequency_mhz;
716         counter_data[COUNTER_VOLTAGE] = voltage_mv;
719 int gator_events_mali_init(void)
721         unsigned int cnt;
723         pr_debug("gator: mali init\n");
725         for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) {
726                 counter_enabled[cnt] = 0;
727                 counter_event[cnt] = 0;
728                 counter_key[cnt] = gator_events_get_key();
729                 counter_address[cnt] = NULL;
730                 counter_data[cnt] = 0;
731         }
733         trace_registered = 0;
735         return gator_events_install(&gator_events_mali_interface);
738 gator_events_init(gator_events_mali_init);