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