Merge tag 'v3.10.49' into linux-linaro-lsk
[firefly-linux-kernel-4.4.55.git] / drivers / gator / gator_events_mali_4xx.c
1 /**
2  * Copyright (C) ARM Limited 2010-2014. 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  */
8
9 #include "gator.h"
10
11 #include <linux/module.h>
12 #include <linux/time.h>
13 #include <linux/math64.h>
14
15 #include "linux/mali_linux_trace.h"
16
17 #include "gator_events_mali_common.h"
18 #include "gator_events_mali_4xx.h"
19
20 /*
21  * There are (currently) four different variants of the comms between gator and Mali:
22  * 1 (deprecated): No software counter support
23  * 2 (deprecated): Tracepoint called for each separate s/w counter value as it appears
24  * 3 (default): Single tracepoint for all s/w counters in a bundle.
25  * Interface style 3 is the default if no other is specified.  1 and 2 will be eliminated when
26  * existing Mali DDKs are upgraded.
27  * 4. As above, but for the Utgard (Mali-450) driver.
28  */
29
30 #if !defined(GATOR_MALI_INTERFACE_STYLE)
31 #define GATOR_MALI_INTERFACE_STYLE (3)
32 #endif
33
34 #if GATOR_MALI_INTERFACE_STYLE < 4
35 #include "mali/mali_mjollnir_profiling_gator_api.h"
36 #else
37 #include "mali/mali_utgard_profiling_gator_api.h"
38 #endif
39
40 /*
41  * Check that the MALI_SUPPORT define is set to one of the allowable device codes.
42  */
43 #if (MALI_SUPPORT != MALI_4xx)
44 #error MALI_SUPPORT set to an invalid device code: expecting MALI_4xx
45 #endif
46
47 /* gatorfs variables for counter enable state,
48  * the event the counter should count and the
49  * 'key' (a unique id set by gatord and returned
50  * by gator.ko)
51  */
52 static unsigned long counter_enabled[NUMBER_OF_EVENTS];
53 static unsigned long counter_event[NUMBER_OF_EVENTS];
54 static unsigned long counter_key[NUMBER_OF_EVENTS];
55
56 /* The data we have recorded */
57 static u32 counter_data[NUMBER_OF_EVENTS];
58 /* The address to sample (or 0 if samples are sent to us) */
59 static u32 *counter_address[NUMBER_OF_EVENTS];
60
61 /* An array used to return the data we recorded
62  * as key,value pairs hence the *2
63  */
64 static unsigned long counter_dump[NUMBER_OF_EVENTS * 2];
65 static unsigned long counter_prev[NUMBER_OF_EVENTS];
66
67 /* Note whether tracepoints have been registered */
68 static int trace_registered;
69
70 /*
71  * These numbers define the actual numbers of each block type that exist in the system. Initially
72  * these are set to the maxima defined above; if the driver is capable of being queried (newer
73  * drivers only) then the values may be revised.
74  */
75 static unsigned int n_vp_cores = MAX_NUM_VP_CORES;
76 static unsigned int n_l2_cores = MAX_NUM_L2_CACHE_CORES;
77 static unsigned int n_fp_cores = MAX_NUM_FP_CORES;
78
79 /**
80  * Calculate the difference and handle the overflow.
81  */
82 static u32 get_difference(u32 start, u32 end)
83 {
84         if (start - end >= 0) {
85                 return start - end;
86         }
87
88         // Mali counters are unsigned 32 bit values that wrap.
89         return (4294967295u - end) + start;
90 }
91
92 /**
93  * Returns non-zero if the given counter ID is an activity counter.
94  */
95 static inline int is_activity_counter(unsigned int event_id)
96 {
97         return (event_id >= FIRST_ACTIVITY_EVENT &&
98                 event_id <= LAST_ACTIVITY_EVENT);
99 }
100
101 /**
102  * Returns non-zero if the given counter ID is a hardware counter.
103  */
104 static inline int is_hw_counter(unsigned int event_id)
105 {
106         return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER);
107 }
108
109 /*
110  * These are provided for utgard compatibility.
111  */
112 typedef void _mali_profiling_get_mali_version_type(struct _mali_profiling_mali_version *values);
113 typedef u32 _mali_profiling_get_l2_counters_type(_mali_profiling_l2_counter_values *values);
114
115 #if GATOR_MALI_INTERFACE_STYLE == 2
116 /**
117  * Returns non-zero if the given counter ID is a software counter.
118  */
119 static inline int is_sw_counter(unsigned int event_id)
120 {
121         return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER);
122 }
123 #endif
124
125 #if GATOR_MALI_INTERFACE_STYLE == 2
126 /*
127  * The Mali DDK uses s64 types to contain software counter values, but gator
128  * can only use a maximum of 32 bits. This function scales a software counter
129  * to an appropriate range.
130  */
131 static u32 scale_sw_counter_value(unsigned int event_id, signed long long value)
132 {
133         u32 scaled_value;
134
135         switch (event_id) {
136         case COUNTER_GLES_UPLOAD_TEXTURE_TIME:
137         case COUNTER_GLES_UPLOAD_VBO_TIME:
138                 scaled_value = (u32)div_s64(value, 1000000);
139                 break;
140         default:
141                 scaled_value = (u32)value;
142                 break;
143         }
144
145         return scaled_value;
146 }
147 #endif
148
149 /* Probe for continuously sampled counter */
150 #if 0                           //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING
151 GATOR_DEFINE_PROBE(mali_sample_address, TP_PROTO(unsigned int event_id, u32 *addr))
152 {
153         /* Turning on too many pr_debug statements in frequently called functions
154          * can cause stability and/or performance problems
155          */
156         //pr_debug("gator: mali_sample_address %d %d\n", event_id, addr);
157         if (event_id >= ACTIVITY_VP && event_id <= COUNTER_FP3_C1) {
158                 counter_address[event_id] = addr;
159         }
160 }
161 #endif
162
163 /* Probe for hardware counter events */
164 GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int value))
165 {
166         /* Turning on too many pr_debug statements in frequently called functions
167          * can cause stability and/or performance problems
168          */
169         //pr_debug("gator: mali_hw_counter %d %d\n", event_id, value);
170         if (is_hw_counter(event_id)) {
171                 counter_data[event_id] = value;
172         }
173 }
174
175 #if GATOR_MALI_INTERFACE_STYLE == 2
176 GATOR_DEFINE_PROBE(mali_sw_counter, TP_PROTO(unsigned int event_id, signed long long value))
177 {
178         if (is_sw_counter(event_id)) {
179                 counter_data[event_id] = scale_sw_counter_value(event_id, value);
180         }
181 }
182 #endif /* GATOR_MALI_INTERFACE_STYLE == 2 */
183
184 #if GATOR_MALI_INTERFACE_STYLE >= 3
185 GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surface_id, unsigned int *counters))
186 {
187         u32 i;
188
189         /* Copy over the values for those counters which are enabled. */
190         for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) {
191                 if (counter_enabled[i]) {
192                         counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]);
193                 }
194         }
195 }
196 #endif /* GATOR_MALI_INTERFACE_STYLE >= 3 */
197
198 /**
199  * Create a single filesystem entry for a specified event.
200  * @param sb the superblock
201  * @param root Filesystem root
202  * @param name The name of the entry to create
203  * @param event The ID of the event
204  * @param create_event_item boolean indicating whether to create an 'event' filesystem entry. True to create.
205  *
206  * @return 0 if ok, non-zero if the create failed.
207  */
208 static int create_fs_entry(struct super_block *sb, struct dentry *root, const char *name, int event, int create_event_item)
209 {
210         struct dentry *dir;
211
212         dir = gatorfs_mkdir(sb, root, name);
213
214         if (!dir) {
215                 return -1;
216         }
217
218         if (create_event_item) {
219                 gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
220         }
221
222         gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
223         gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
224
225         return 0;
226 }
227
228 #if GATOR_MALI_INTERFACE_STYLE > 3
229 /*
230  * Read the version info structure if available
231  */
232 static void initialise_version_info(void)
233 {
234         _mali_profiling_get_mali_version_type *mali_profiling_get_mali_version_symbol;
235
236         mali_profiling_get_mali_version_symbol = symbol_get(_mali_profiling_get_mali_version);
237
238         if (mali_profiling_get_mali_version_symbol) {
239                 struct _mali_profiling_mali_version version_info;
240
241                 pr_debug("gator: mali online _mali_profiling_get_mali_version symbol @ %p\n",
242                                 mali_profiling_get_mali_version_symbol);
243
244                 /*
245                  * Revise the number of each different core type using information derived from the DDK.
246                  */
247                 mali_profiling_get_mali_version_symbol(&version_info);
248
249                 n_fp_cores = version_info.num_of_fp_cores;
250                 n_vp_cores = version_info.num_of_vp_cores;
251                 n_l2_cores = version_info.num_of_l2_cores;
252
253                 /* Release the function - we're done with it. */
254                 symbol_put(_mali_profiling_get_mali_version);
255         } else {
256                 printk("gator: mali online _mali_profiling_get_mali_version symbol not found\n");
257         }
258 }
259 #endif
260
261 static int create_files(struct super_block *sb, struct dentry *root)
262 {
263         int event;
264         const char *mali_name = gator_mali_get_mali_name();
265
266         char buf[40];
267         int core_id;
268         int counter_number;
269
270         pr_debug("gator: Initialising counters with style = %d\n", GATOR_MALI_INTERFACE_STYLE);
271
272 #if GATOR_MALI_INTERFACE_STYLE > 3
273         /*
274          * Initialise first: this sets up the number of cores available (on compatible DDK versions).
275          * Ideally this would not need guarding but other parts of the code depend on the interface style being set
276          * correctly; if it is not then the system can enter an inconsistent state.
277          */
278         initialise_version_info();
279 #endif
280
281         /* Vertex processor counters */
282         for (core_id = 0; core_id < n_vp_cores; core_id++) {
283                 int activity_counter_id = ACTIVITY_VP_0;
284                 snprintf(buf, sizeof buf, "ARM_%s_VP_%d_active", mali_name, core_id);
285                 if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0) {
286                         return -1;
287                 }
288
289                 for (counter_number = 0; counter_number < 2; counter_number++) {
290                         int counter_id = COUNTER_VP_0_C0 + (2 * core_id) + counter_number;
291
292                         snprintf(buf, sizeof buf, "ARM_%s_VP_%d_cnt%d", mali_name, core_id, counter_number);
293                         if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) {
294                                 return -1;
295                         }
296                 }
297         }
298
299         /* Fragment processors' counters */
300         for (core_id = 0; core_id < n_fp_cores; core_id++) {
301                 int activity_counter_id = ACTIVITY_FP_0 + core_id;
302
303                 snprintf(buf, sizeof buf, "ARM_%s_FP_%d_active", mali_name, core_id);
304                 if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0) {
305                         return -1;
306                 }
307
308                 for (counter_number = 0; counter_number < 2; counter_number++) {
309                         int counter_id = COUNTER_FP_0_C0 + (2 * core_id) + counter_number;
310
311                         snprintf(buf, sizeof buf, "ARM_%s_FP_%d_cnt%d", mali_name, core_id, counter_number);
312                         if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) {
313                                 return -1;
314                         }
315                 }
316         }
317
318         /* L2 Cache counters */
319         for (core_id = 0; core_id < n_l2_cores; core_id++) {
320                 for (counter_number = 0; counter_number < 2; counter_number++) {
321                         int counter_id = COUNTER_L2_0_C0 + (2 * core_id) + counter_number;
322
323                         snprintf(buf, sizeof buf, "ARM_%s_L2_%d_cnt%d", mali_name, core_id, counter_number);
324                         if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) {
325                                 return -1;
326                         }
327                 }
328         }
329
330         /* Now set up the software counter entries */
331         for (event = FIRST_SW_COUNTER; event <= LAST_SW_COUNTER; event++) {
332                 snprintf(buf, sizeof(buf), "ARM_%s_SW_%d", mali_name, event - FIRST_SW_COUNTER);
333
334                 if (create_fs_entry(sb, root, buf, event, 0) != 0) {
335                         return -1;
336                 }
337         }
338
339         /* Now set up the special counter entries */
340         snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip_cnt0", mali_name);
341         if (create_fs_entry(sb, root, buf, COUNTER_FILMSTRIP, 1) != 0) {
342                 return -1;
343         }
344
345 #ifdef DVFS_REPORTED_BY_DDK
346         snprintf(buf, sizeof(buf), "ARM_%s_Frequency", mali_name);
347         if (create_fs_entry(sb, root, buf, COUNTER_FREQUENCY, 1) != 0) {
348                 return -1;
349         }
350
351         snprintf(buf, sizeof(buf), "ARM_%s_Voltage", mali_name);
352         if (create_fs_entry(sb, root, buf, COUNTER_VOLTAGE, 1) != 0) {
353                 return -1;
354         }
355 #endif
356
357         return 0;
358 }
359
360 /*
361  * Local store for the get_counters entry point into the DDK.
362  * This is stored here since it is used very regularly.
363  */
364 static mali_profiling_get_counters_type *mali_get_counters = NULL;
365 static _mali_profiling_get_l2_counters_type *mali_get_l2_counters = NULL;
366
367 /*
368  * Examine list of counters between two index limits and determine if any one is enabled.
369  * Returns 1 if any counter is enabled, 0 if none is.
370  */
371 static int is_any_counter_enabled(unsigned int first_counter, unsigned int last_counter)
372 {
373         unsigned int i;
374
375         for (i = first_counter; i <= last_counter; i++) {
376                 if (counter_enabled[i]) {
377                         return 1;       /* At least one counter is enabled */
378                 }
379         }
380
381         return 0;               /* No s/w counters enabled */
382 }
383
384 static void init_counters(unsigned int from_counter, unsigned int to_counter)
385 {
386         unsigned int counter_id;
387
388         /* If a Mali driver is present and exporting the appropriate symbol
389          * then we can request the HW counters (of which there are only 2)
390          * be configured to count the desired events
391          */
392         mali_profiling_set_event_type *mali_set_hw_event;
393
394         mali_set_hw_event = symbol_get(_mali_profiling_set_event);
395
396         if (mali_set_hw_event) {
397                 pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n", mali_set_hw_event);
398
399                 for (counter_id = from_counter; counter_id <= to_counter; counter_id++) {
400                         if (counter_enabled[counter_id]) {
401                                 mali_set_hw_event(counter_id, counter_event[counter_id]);
402                         } else {
403                                 mali_set_hw_event(counter_id, 0xFFFFFFFF);
404                         }
405                 }
406
407                 symbol_put(_mali_profiling_set_event);
408         } else {
409                 printk("gator: mali online _mali_profiling_set_event symbol not found\n");
410         }
411 }
412
413 static void mali_counter_initialize(void)
414 {
415         int i;
416         int core_id;
417
418         mali_profiling_control_type *mali_control;
419
420         init_counters(COUNTER_L2_0_C0, COUNTER_L2_0_C0 + (2 * n_l2_cores) - 1);
421         init_counters(COUNTER_VP_0_C0, COUNTER_VP_0_C0 + (2 * n_vp_cores) - 1);
422         init_counters(COUNTER_FP_0_C0, COUNTER_FP_0_C0 + (2 * n_fp_cores) - 1);
423
424         /* Generic control interface for Mali DDK. */
425         mali_control = symbol_get(_mali_profiling_control);
426         if (mali_control) {
427                 /* The event attribute in the XML file keeps the actual frame rate. */
428                 unsigned int rate = counter_event[COUNTER_FILMSTRIP] & 0xff;
429                 unsigned int resize_factor = (counter_event[COUNTER_FILMSTRIP] >> 8) & 0xff;
430
431                 pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control);
432
433                 mali_control(SW_COUNTER_ENABLE, (is_any_counter_enabled(FIRST_SW_COUNTER, LAST_SW_COUNTER) ? 1 : 0));
434                 mali_control(FBDUMP_CONTROL_ENABLE, (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0));
435                 mali_control(FBDUMP_CONTROL_RATE, rate);
436                 mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor);
437
438                 pr_debug("gator: sent mali_control enabled=%d, rate=%d\n", (counter_enabled[COUNTER_FILMSTRIP] ? 1 : 0), rate);
439
440                 symbol_put(_mali_profiling_control);
441         } else {
442                 printk("gator: mali online _mali_profiling_control symbol not found\n");
443         }
444
445         mali_get_counters = symbol_get(_mali_profiling_get_counters);
446         if (mali_get_counters) {
447                 pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", mali_get_counters);
448
449         } else {
450                 pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined");
451         }
452
453         mali_get_l2_counters = symbol_get(_mali_profiling_get_l2_counters);
454         if (mali_get_l2_counters) {
455                 pr_debug("gator: mali online _mali_profiling_get_l2_counters symbol @ %p\n", mali_get_l2_counters);
456
457         } else {
458                 pr_debug("gator WARNING: mali _mali_profiling_get_l2_counters symbol not defined");
459         }
460
461         if (!mali_get_counters && !mali_get_l2_counters) {
462                 pr_debug("gator: WARNING: no L2 counters available");
463                 n_l2_cores = 0;
464         }
465
466         for (core_id = 0; core_id < n_l2_cores; core_id++) {
467                 int counter_id = COUNTER_L2_0_C0 + (2 * core_id);
468                 counter_prev[counter_id] = 0;
469                 counter_prev[counter_id + 1] = 0;
470         }
471
472         /* Clear counters in the start */
473         for (i = 0; i < NUMBER_OF_EVENTS; i++) {
474                 counter_data[i] = 0;
475         }
476 }
477
478 static void mali_counter_deinitialize(void)
479 {
480         mali_profiling_set_event_type *mali_set_hw_event;
481         mali_profiling_control_type *mali_control;
482
483         mali_set_hw_event = symbol_get(_mali_profiling_set_event);
484
485         if (mali_set_hw_event) {
486                 int i;
487
488                 pr_debug("gator: mali offline _mali_profiling_set_event symbol @ %p\n", mali_set_hw_event);
489                 for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
490                         mali_set_hw_event(i, 0xFFFFFFFF);
491                 }
492
493                 symbol_put(_mali_profiling_set_event);
494         } else {
495                 printk("gator: mali offline _mali_profiling_set_event symbol not found\n");
496         }
497
498         /* Generic control interface for Mali DDK. */
499         mali_control = symbol_get(_mali_profiling_control);
500
501         if (mali_control) {
502                 pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_control);
503
504                 /* Reset the DDK state - disable counter collection */
505                 mali_control(SW_COUNTER_ENABLE, 0);
506
507                 mali_control(FBDUMP_CONTROL_ENABLE, 0);
508
509                 symbol_put(_mali_profiling_control);
510         } else {
511                 printk("gator: mali offline _mali_profiling_control symbol not found\n");
512         }
513
514         if (mali_get_counters) {
515                 symbol_put(_mali_profiling_get_counters);
516         }
517
518         if (mali_get_l2_counters) {
519                 symbol_put(_mali_profiling_get_l2_counters);
520         }
521 }
522
523 static int start(void)
524 {
525         // register tracepoints
526         if (GATOR_REGISTER_TRACE(mali_hw_counter)) {
527                 printk("gator: mali_hw_counter tracepoint failed to activate\n");
528                 return -1;
529         }
530
531 #if GATOR_MALI_INTERFACE_STYLE == 1
532         /* None. */
533 #elif GATOR_MALI_INTERFACE_STYLE == 2
534         /* For patched Mali driver. */
535         if (GATOR_REGISTER_TRACE(mali_sw_counter)) {
536                 printk("gator: mali_sw_counter tracepoint failed to activate\n");
537                 return -1;
538         }
539 #elif GATOR_MALI_INTERFACE_STYLE >= 3
540         /* For Mali drivers with built-in support. */
541         if (GATOR_REGISTER_TRACE(mali_sw_counters)) {
542                 printk("gator: mali_sw_counters tracepoint failed to activate\n");
543                 return -1;
544         }
545 #else
546 #error Unknown GATOR_MALI_INTERFACE_STYLE option.
547 #endif
548
549         trace_registered = 1;
550
551         mali_counter_initialize();
552         return 0;
553 }
554
555 static void stop(void)
556 {
557         unsigned int cnt;
558
559         pr_debug("gator: mali stop\n");
560
561         if (trace_registered) {
562                 GATOR_UNREGISTER_TRACE(mali_hw_counter);
563
564 #if GATOR_MALI_INTERFACE_STYLE == 1
565                 /* None. */
566 #elif GATOR_MALI_INTERFACE_STYLE == 2
567                 /* For patched Mali driver. */
568                 GATOR_UNREGISTER_TRACE(mali_sw_counter);
569 #elif GATOR_MALI_INTERFACE_STYLE >= 3
570                 /* For Mali drivers with built-in support. */
571                 GATOR_UNREGISTER_TRACE(mali_sw_counters);
572 #else
573 #error Unknown GATOR_MALI_INTERFACE_STYLE option.
574 #endif
575
576                 pr_debug("gator: mali timeline tracepoint deactivated\n");
577
578                 trace_registered = 0;
579         }
580
581         for (cnt = 0; cnt < NUMBER_OF_EVENTS; cnt++) {
582                 counter_enabled[cnt] = 0;
583                 counter_event[cnt] = 0;
584                 counter_address[cnt] = NULL;
585         }
586
587         mali_counter_deinitialize();
588 }
589
590 static void dump_counters(unsigned int from_counter, unsigned int to_counter, unsigned int *len)
591 {
592         unsigned int counter_id;
593
594         for (counter_id = from_counter; counter_id <= to_counter; counter_id++) {
595                 if (counter_enabled[counter_id]) {
596                         counter_dump[(*len)++] = counter_key[counter_id];
597                         counter_dump[(*len)++] = counter_data[counter_id];
598
599                         counter_data[counter_id] = 0;
600                 }
601         }
602 }
603
604 static int read(int **buffer)
605 {
606         int len = 0;
607
608         if (!on_primary_core())
609                 return 0;
610
611         // Read the L2 C0 and C1 here.
612         if (n_l2_cores > 0 && is_any_counter_enabled(COUNTER_L2_0_C0, COUNTER_L2_0_C0 + (2 * n_l2_cores))) {
613                 unsigned int unavailable_l2_caches = 0;
614                 _mali_profiling_l2_counter_values cache_values;
615                 unsigned int cache_id;
616                 struct _mali_profiling_core_counters *per_core;
617
618                 /* Poke the driver to get the counter values - older style; only one L2 cache */
619                 if (mali_get_l2_counters) {
620                         unavailable_l2_caches = mali_get_l2_counters(&cache_values);
621                 } else if (mali_get_counters) {
622                         per_core = &cache_values.cores[0];
623                         mali_get_counters(&per_core->source0, &per_core->value0, &per_core->source1, &per_core->value1);
624                 } else {
625                         /* This should never happen, as n_l2_caches is only set > 0 if one of the above functions is found. */
626                 }
627
628                 /* Fill in the two cache counter values for each cache block. */
629                 for (cache_id = 0; cache_id < n_l2_cores; cache_id++) {
630                         unsigned int counter_id_0 = COUNTER_L2_0_C0 + (2 * cache_id);
631                         unsigned int counter_id_1 = counter_id_0 + 1;
632
633                         if ((1 << cache_id) & unavailable_l2_caches) {
634                                 continue; /* This cache is unavailable (powered-off, possibly). */
635                         }
636
637                         per_core = &cache_values.cores[cache_id];
638
639                         if (counter_enabled[counter_id_0]) {
640                                 // Calculate and save src0's counter val0
641                                 counter_dump[len++] = counter_key[counter_id_0];
642                                 counter_dump[len++] = get_difference(per_core->value0, counter_prev[counter_id_0]);
643                         }
644
645                         if (counter_enabled[counter_id_1]) {
646                                 // Calculate and save src1's counter val1
647                                 counter_dump[len++] = counter_key[counter_id_1];
648                                 counter_dump[len++] = get_difference(per_core->value1, counter_prev[counter_id_1]);
649                         }
650
651                         // Save the previous values for the counters.
652                         counter_prev[counter_id_0] = per_core->value0;
653                         counter_prev[counter_id_1] = per_core->value1;
654                 }
655         }
656
657         /* Process other (non-timeline) counters. */
658         dump_counters(COUNTER_VP_0_C0, COUNTER_VP_0_C0 + (2 * n_vp_cores) - 1, &len);
659         dump_counters(COUNTER_FP_0_C0, COUNTER_FP_0_C0 + (2 * n_fp_cores) - 1, &len);
660
661         dump_counters(FIRST_SW_COUNTER, LAST_SW_COUNTER, &len);
662
663 #ifdef DVFS_REPORTED_BY_DDK
664         {
665                 int cnt;
666                 /*
667                  * Add in the voltage and frequency counters if enabled.  Note that, since these are
668                  * actually passed as events, the counter value should not be cleared.
669                  */
670                 cnt = COUNTER_FREQUENCY;
671                 if (counter_enabled[cnt]) {
672                         counter_dump[len++] = counter_key[cnt];
673                         counter_dump[len++] = counter_data[cnt];
674                 }
675
676                 cnt = COUNTER_VOLTAGE;
677                 if (counter_enabled[cnt]) {
678                         counter_dump[len++] = counter_key[cnt];
679                         counter_dump[len++] = counter_data[cnt];
680                 }
681         }
682 #endif
683
684         if (buffer) {
685                 *buffer = (int *)counter_dump;
686         }
687
688         return len;
689 }
690
691 static struct gator_interface gator_events_mali_interface = {
692         .create_files = create_files,
693         .start = start,
694         .stop = stop,
695         .read = read,
696 };
697
698 extern void gator_events_mali_log_dvfs_event(unsigned int frequency_mhz, unsigned int voltage_mv)
699 {
700 #ifdef DVFS_REPORTED_BY_DDK
701         counter_data[COUNTER_FREQUENCY] = frequency_mhz;
702         counter_data[COUNTER_VOLTAGE] = voltage_mv;
703 #endif
704 }
705
706 int gator_events_mali_init(void)
707 {
708         unsigned int cnt;
709
710         pr_debug("gator: mali init\n");
711
712         for (cnt = 0; 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         }
719
720         trace_registered = 0;
721
722         return gator_events_install(&gator_events_mali_interface);
723 }