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 /*
21 * There are (currently) three 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 */
29 #if !defined(GATOR_MALI_INTERFACE_STYLE)
30 #define GATOR_MALI_INTERFACE_STYLE (3)
31 #endif
33 /*
34 * List of possible actions allowing DDK to be controlled by Streamline.
35 * The following numbers are used by DDK to control the frame buffer dumping.
36 */
37 #define FBDUMP_CONTROL_ENABLE (1)
38 #define FBDUMP_CONTROL_RATE (2)
39 #define SW_EVENTS_ENABLE (3)
40 #define FBDUMP_CONTROL_RESIZE_FACTOR (4)
42 /*
43 * Check that the MALI_SUPPORT define is set to one of the allowable device codes.
44 */
45 #if (MALI_SUPPORT != MALI_400)
46 #error MALI_SUPPORT set to an invalid device code: expecting MALI_400
47 #endif
49 /*
50 * The number of fragment processors. Update to suit your hardware implementation.
51 */
52 #define NUM_FP_UNITS (4)
54 enum counters {
55 /* Timeline activity */
56 ACTIVITY_VP = 0,
57 ACTIVITY_FP0,
58 ACTIVITY_FP1,
59 ACTIVITY_FP2,
60 ACTIVITY_FP3,
62 /* L2 cache counters */
63 COUNTER_L2_C0,
64 COUNTER_L2_C1,
66 /* Vertex processor counters */
67 COUNTER_VP_C0,
68 COUNTER_VP_C1,
70 /* Fragment processor counters */
71 COUNTER_FP0_C0,
72 COUNTER_FP0_C1,
73 COUNTER_FP1_C0,
74 COUNTER_FP1_C1,
75 COUNTER_FP2_C0,
76 COUNTER_FP2_C1,
77 COUNTER_FP3_C0,
78 COUNTER_FP3_C1,
80 /* EGL Software Counters */
81 COUNTER_EGL_BLIT_TIME,
83 /* GLES Software Counters */
84 COUNTER_GLES_DRAW_ELEMENTS_CALLS,
85 COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES,
86 COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED,
87 COUNTER_GLES_DRAW_ARRAYS_CALLS,
88 COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED,
89 COUNTER_GLES_DRAW_POINTS,
90 COUNTER_GLES_DRAW_LINES,
91 COUNTER_GLES_DRAW_LINE_LOOP,
92 COUNTER_GLES_DRAW_LINE_STRIP,
93 COUNTER_GLES_DRAW_TRIANGLES,
94 COUNTER_GLES_DRAW_TRIANGLE_STRIP,
95 COUNTER_GLES_DRAW_TRIANGLE_FAN,
96 COUNTER_GLES_NON_VBO_DATA_COPY_TIME,
97 COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI,
98 COUNTER_GLES_UPLOAD_TEXTURE_TIME,
99 COUNTER_GLES_UPLOAD_VBO_TIME,
100 COUNTER_GLES_NUM_FLUSHES,
101 COUNTER_GLES_NUM_VSHADERS_GENERATED,
102 COUNTER_GLES_NUM_FSHADERS_GENERATED,
103 COUNTER_GLES_VSHADER_GEN_TIME,
104 COUNTER_GLES_FSHADER_GEN_TIME,
105 COUNTER_GLES_INPUT_TRIANGLES,
106 COUNTER_GLES_VXCACHE_HIT,
107 COUNTER_GLES_VXCACHE_MISS,
108 COUNTER_GLES_VXCACHE_COLLISION,
109 COUNTER_GLES_CULLED_TRIANGLES,
110 COUNTER_GLES_CULLED_LINES,
111 COUNTER_GLES_BACKFACE_TRIANGLES,
112 COUNTER_GLES_GBCLIP_TRIANGLES,
113 COUNTER_GLES_GBCLIP_LINES,
114 COUNTER_GLES_TRIANGLES_DRAWN,
115 COUNTER_GLES_DRAWCALL_TIME,
116 COUNTER_GLES_TRIANGLES_COUNT,
117 COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT,
118 COUNTER_GLES_STRIP_TRIANGLES_COUNT,
119 COUNTER_GLES_FAN_TRIANGLES_COUNT,
120 COUNTER_GLES_LINES_COUNT,
121 COUNTER_GLES_INDEPENDENT_LINES_COUNT,
122 COUNTER_GLES_STRIP_LINES_COUNT,
123 COUNTER_GLES_LOOP_LINES_COUNT,
125 COUNTER_FILMSTRIP,
126 COUNTER_FREQUENCY,
127 COUNTER_VOLTAGE,
129 NUMBER_OF_EVENTS
130 };
132 #define FIRST_ACTIVITY_EVENT ACTIVITY_VP
133 #define LAST_ACTIVITY_EVENT ACTIVITY_FP3
135 #define FIRST_HW_COUNTER COUNTER_L2_C0
136 #define LAST_HW_COUNTER COUNTER_FP3_C1
138 #define FIRST_SW_COUNTER COUNTER_EGL_BLIT_TIME
139 #define LAST_SW_COUNTER COUNTER_GLES_LOOP_LINES_COUNT
141 #define FIRST_SPECIAL_COUNTER COUNTER_FILMSTRIP
142 #define LAST_SPECIAL_COUNTER COUNTER_VOLTAGE
144 /* gatorfs variables for counter enable state,
145 * the event the counter should count and the
146 * 'key' (a unique id set by gatord and returned
147 * by gator.ko)
148 */
149 static unsigned long counter_enabled[NUMBER_OF_EVENTS];
150 static unsigned long counter_event[NUMBER_OF_EVENTS];
151 static unsigned long counter_key[NUMBER_OF_EVENTS];
153 /* The data we have recorded */
154 static u32 counter_data[NUMBER_OF_EVENTS];
155 /* The address to sample (or 0 if samples are sent to us) */
156 static u32* counter_address[NUMBER_OF_EVENTS];
158 /* An array used to return the data we recorded
159 * as key,value pairs hence the *2
160 */
161 static unsigned long counter_dump[NUMBER_OF_EVENTS * 2];
162 static unsigned long counter_prev[NUMBER_OF_EVENTS];
164 /* Note whether tracepoints have been registered */
165 static int trace_registered;
167 /**
168 * Calculate the difference and handle the overflow.
169 */
170 static u32 get_difference(u32 start, u32 end)
171 {
172 if (start - end >= 0)
173 {
174 return start - end;
175 }
177 // Mali counters are unsigned 32 bit values that wrap.
178 return (4294967295u - end) + start;
179 }
181 /**
182 * Returns non-zero if the given counter ID is an activity counter.
183 */
184 static inline int is_activity_counter(unsigned int event_id)
185 {
186 return (event_id >= FIRST_ACTIVITY_EVENT &&
187 event_id <= LAST_ACTIVITY_EVENT);
188 }
190 /**
191 * Returns non-zero if the given counter ID is a hardware counter.
192 */
193 static inline int is_hw_counter(unsigned int event_id)
194 {
195 return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER);
196 }
198 #if GATOR_MALI_INTERFACE_STYLE == 2
199 /**
200 * Returns non-zero if the given counter ID is a software counter.
201 */
202 static inline int is_sw_counter(unsigned int event_id)
203 {
204 return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER);
205 }
206 #endif
208 #if GATOR_MALI_INTERFACE_STYLE == 2
209 /*
210 * The Mali DDK uses s64 types to contain software counter values, but gator
211 * can only use a maximum of 32 bits. This function scales a software counter
212 * to an appopriate range.
213 */
214 static u32 scale_sw_counter_value(unsigned int event_id, signed long long value)
215 {
216 u32 scaled_value;
218 switch (event_id) {
219 case COUNTER_GLES_UPLOAD_TEXTURE_TIME:
220 case COUNTER_GLES_UPLOAD_VBO_TIME:
221 scaled_value = (u32)div_s64(value, 1000000);
222 break;
223 default:
224 scaled_value = (u32)value;
225 break;
226 }
228 return scaled_value;
229 }
230 #endif
232 /* Probe for continuously sampled counter */
233 #if 0 //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING
234 GATOR_DEFINE_PROBE(mali_sample_address, TP_PROTO(unsigned int event_id, u32* addr))
235 {
236 /* Turning on too many pr_debug statements in frequently called functions
237 * can cause stability and/or performance problems
238 */
239 //pr_debug("gator: mali_sample_address %d %d\n", event_id, addr);
240 if (event_id >= ACTIVITY_VP && event_id <= COUNTER_FP3_C1) {
241 counter_address[event_id] = addr;
242 }
243 }
244 #endif
246 /* Probe for hardware counter events */
247 GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int value))
248 {
249 /* Turning on too many pr_debug statements in frequently called functions
250 * can cause stability and/or performance problems
251 */
252 //pr_debug("gator: mali_hw_counter %d %d\n", event_id, value);
253 if (is_hw_counter(event_id)) {
254 counter_data[event_id] = value;
255 }
256 }
258 #if GATOR_MALI_INTERFACE_STYLE == 2
259 GATOR_DEFINE_PROBE(mali_sw_counter, TP_PROTO(unsigned int event_id, signed long long value))
260 {
261 if (is_sw_counter(event_id)) {
262 counter_data[event_id] = scale_sw_counter_value(event_id, value);
263 }
264 }
265 #endif /* GATOR_MALI_INTERFACE_STYLE == 2 */
268 #if GATOR_MALI_INTERFACE_STYLE == 3
269 GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void * surface_id, unsigned int * counters))
270 {
271 u32 i;
273 /* Copy over the values for those counters which are enabled. */
274 for(i=FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++)
275 {
276 if(counter_enabled[i])
277 {
278 counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]);
279 }
280 }
281 }
282 #endif /* GATOR_MALI_INTERFACE_STYLE == 3 */
284 static int create_files(struct super_block *sb, struct dentry *root) {
285 struct dentry *dir;
286 int event;
287 int n_fp = NUM_FP_UNITS;
289 const char* mali_name = gator_mali_get_mali_name();
291 /*
292 * Create the filesystem entries for vertex processor, fragement processor
293 * and L2 cache timeline and hardware counters. Software counters get
294 * special handling after this block.
295 */
296 for (event = FIRST_ACTIVITY_EVENT; event <= LAST_HW_COUNTER; event++)
297 {
298 char buf[40];
300 /*
301 * We can skip this event if it's for a non-existent fragment
302 * processor.
303 */
304 if (((event - ACTIVITY_FP0 >= n_fp) && (event < COUNTER_L2_C0)) ||
305 (((event - COUNTER_FP0_C0)/2 >= n_fp)))
306 {
307 continue;
308 }
310 /* Otherwise, set up the filesystem entry for this event. */
311 switch (event) {
312 case ACTIVITY_VP:
313 snprintf(buf, sizeof buf, "ARM_%s_VP_active", mali_name);
314 break;
315 case ACTIVITY_FP0:
316 case ACTIVITY_FP1:
317 case ACTIVITY_FP2:
318 case ACTIVITY_FP3:
319 snprintf(buf, sizeof buf, "ARM_%s_FP%d_active",
320 mali_name, event - ACTIVITY_FP0);
321 break;
322 case COUNTER_L2_C0:
323 case COUNTER_L2_C1:
324 snprintf(buf, sizeof buf, "ARM_%s_L2_cnt%d",
325 mali_name, event - COUNTER_L2_C0);
326 break;
327 case COUNTER_VP_C0:
328 case COUNTER_VP_C1:
329 snprintf(buf, sizeof buf, "ARM_%s_VP_cnt%d",
330 mali_name, event - COUNTER_VP_C0);
331 break;
332 case COUNTER_FP0_C0:
333 case COUNTER_FP0_C1:
334 case COUNTER_FP1_C0:
335 case COUNTER_FP1_C1:
336 case COUNTER_FP2_C0:
337 case COUNTER_FP2_C1:
338 case COUNTER_FP3_C0:
339 case COUNTER_FP3_C1:
340 snprintf(buf, sizeof buf, "ARM_%s_FP%d_cnt%d", mali_name,
341 (event - COUNTER_FP0_C0) / 2, (event - COUNTER_FP0_C0) % 2);
342 break;
343 default:
344 printk("gator: trying to create file for non-existent counter (%d)\n", event);
345 continue;
346 }
348 dir = gatorfs_mkdir(sb, root, buf);
350 if (!dir) {
351 return -1;
352 }
354 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
356 /* Only create an event node for counters that can change what they count */
357 if (event >= COUNTER_L2_C0) {
358 gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
359 }
361 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
362 }
364 /* Now set up the software counter entries */
365 for (event = FIRST_SW_COUNTER; event <= LAST_SW_COUNTER; event++)
366 {
367 char buf[40];
369 snprintf(buf, sizeof(buf), "ARM_%s_SW_%d", mali_name, event);
371 dir = gatorfs_mkdir(sb, root, buf);
373 if (!dir) {
374 return -1;
375 }
377 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
378 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
379 }
381 /* Now set up the special counter entries */
382 for (event = FIRST_SPECIAL_COUNTER; event <= LAST_SPECIAL_COUNTER; event++)
383 {
384 char buf[40];
386 switch(event) {
387 case COUNTER_FILMSTRIP:
388 snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip", mali_name);
389 break;
391 case COUNTER_FREQUENCY:
392 snprintf(buf, sizeof(buf), "ARM_%s_Frequency", mali_name);
393 break;
395 case COUNTER_VOLTAGE:
396 snprintf(buf, sizeof(buf), "ARM_%s_Voltage", mali_name);
397 break;
399 default:
400 break;
401 }
403 dir = gatorfs_mkdir(sb, root, buf);
405 if (!dir) {
406 return -1;
407 }
409 gatorfs_create_ulong(sb, dir, "event", &counter_event[event]);
410 gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]);
411 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
412 }
414 return 0;
415 }
417 /*
418 * Local store for the get_counters entry point into the DDK.
419 * This is stored here since it is used very regularly.
420 */
421 static mali_profiling_get_counters_type *mali_get_counters = NULL;
423 /*
424 * Examine list of software counters and determine if any one is enabled.
425 * Returns 1 if any counter is enabled, 0 if none is.
426 */
427 static int is_any_sw_counter_enabled(void)
428 {
429 unsigned int i;
431 for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++)
432 {
433 if (counter_enabled[i])
434 {
435 return 1; /* At least one counter is enabled */
436 }
437 }
439 return 0; /* No s/w counters enabled */
440 }
442 static void mali_counter_initialize(void)
443 {
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 }
511 else{
512 pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined");
513 }
514 }
516 static void mali_counter_deinitialize(void)
517 {
518 mali_profiling_set_event_type *mali_set_hw_event;
519 mali_osk_fb_control_set_type *mali_set_fb_event;
520 mali_profiling_control_type *mali_control;
522 mali_set_hw_event = symbol_get(_mali_profiling_set_event);
524 if (mali_set_hw_event) {
525 int i;
527 pr_debug("gator: mali offline _mali_profiling_set_event symbol @ %p\n",mali_set_hw_event);
528 for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
529 mali_set_hw_event(i, 0xFFFFFFFF);
530 }
532 symbol_put(_mali_profiling_set_event);
533 } else {
534 printk("gator: mali offline _mali_profiling_set_event symbol not found\n");
535 }
537 mali_set_fb_event = symbol_get(_mali_osk_fb_control_set);
539 if (mali_set_fb_event) {
540 pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
542 mali_set_fb_event(0,0);
544 symbol_put(_mali_osk_fb_control_set);
545 } else {
546 printk("gator: mali offline _mali_osk_fb_control_set symbol not found\n");
547 }
549 /* Generic control interface for Mali DDK. */
550 mali_control = symbol_get(_mali_profiling_control);
552 if (mali_control) {
553 pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_set_fb_event);
555 /* Reset the DDK state - disable counter collection */
556 mali_control(SW_EVENTS_ENABLE, 0);
558 mali_control(FBDUMP_CONTROL_ENABLE, 0);
560 symbol_put(_mali_profiling_control);
561 } else {
562 printk("gator: mali offline _mali_profiling_control symbol not found\n");
563 }
565 if (mali_get_counters){
566 symbol_put(_mali_profiling_get_counters);
567 }
569 }
571 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;
600 }
602 static void stop(void) {
603 unsigned int cnt;
605 pr_debug("gator: mali stop\n");
607 if (trace_registered) {
608 GATOR_UNREGISTER_TRACE(mali_hw_counter);
610 #if GATOR_MALI_INTERFACE_STYLE == 1
611 /* None. */
612 #elif GATOR_MALI_INTERFACE_STYLE == 2
613 /* For patched Mali driver. */
614 GATOR_UNREGISTER_TRACE(mali_sw_counter);
615 #elif GATOR_MALI_INTERFACE_STYLE == 3
616 /* For Mali drivers with built-in support. */
617 GATOR_UNREGISTER_TRACE(mali_sw_counters);
618 #else
619 #error Unknown GATOR_MALI_INTERFACE_STYLE option.
620 #endif
622 pr_debug("gator: mali timeline tracepoint deactivated\n");
624 trace_registered = 0;
625 }
627 for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) {
628 counter_enabled[cnt] = 0;
629 counter_event[cnt] = 0;
630 counter_address[cnt] = NULL;
631 }
633 mali_counter_deinitialize();
634 }
636 static int read(int **buffer) {
637 int cnt, len = 0;
639 if (smp_processor_id()) return 0;
641 // Read the L2 C0 and C1 here.
642 if (counter_enabled[COUNTER_L2_C0] || counter_enabled[COUNTER_L2_C1] ) {
643 u32 src0 = 0;
644 u32 val0 = 0;
645 u32 src1 = 0;
646 u32 val1 = 0;
648 // Poke the driver to get the counter values
649 if (mali_get_counters){
650 mali_get_counters(&src0, &val0, &src1, &val1);
651 }
653 if (counter_enabled[COUNTER_L2_C0])
654 {
655 // Calculate and save src0's counter val0
656 counter_dump[len++] = counter_key[COUNTER_L2_C0];
657 counter_dump[len++] = get_difference(val0, counter_prev[COUNTER_L2_C0]);
658 }
660 if (counter_enabled[COUNTER_L2_C1])
661 {
662 // Calculate and save src1's counter val1
663 counter_dump[len++] = counter_key[COUNTER_L2_C1];
664 counter_dump[len++] = get_difference(val1, counter_prev[COUNTER_L2_C1]);
665 }
667 // Save the previous values for the counters.
668 counter_prev[COUNTER_L2_C0] = val0;
669 counter_prev[COUNTER_L2_C1] = val1;
670 }
672 // Process other (non-timeline) counters.
673 for (cnt = COUNTER_VP_C0; cnt <= LAST_SW_COUNTER; cnt++) {
674 if (counter_enabled[cnt]) {
675 counter_dump[len++] = counter_key[cnt];
676 counter_dump[len++] = counter_data[cnt];
678 counter_data[cnt] = 0;
679 }
680 }
682 /*
683 * Add in the voltage and frequency counters if enabled. Note that, since these are
684 * actually passed as events, the counter value should not be cleared.
685 */
686 cnt = COUNTER_FREQUENCY;
687 if (counter_enabled[cnt]) {
688 counter_dump[len++] = counter_key[cnt];
689 counter_dump[len++] = counter_data[cnt];
690 }
692 cnt = COUNTER_VOLTAGE;
693 if (counter_enabled[cnt]) {
694 counter_dump[len++] = counter_key[cnt];
695 counter_dump[len++] = counter_data[cnt];
696 }
699 if (buffer) {
700 *buffer = (int*) counter_dump;
701 }
703 return len;
704 }
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) {
714 counter_data[COUNTER_FREQUENCY] = frequency_mhz;
715 counter_data[COUNTER_VOLTAGE] = voltage_mv;
716 }
718 int gator_events_mali_init(void)
719 {
720 unsigned int cnt;
722 pr_debug("gator: mali init\n");
724 for (cnt = FIRST_ACTIVITY_EVENT; cnt < NUMBER_OF_EVENTS; cnt++) {
725 counter_enabled[cnt] = 0;
726 counter_event[cnt] = 0;
727 counter_key[cnt] = gator_events_get_key();
728 counter_address[cnt] = NULL;
729 counter_data[cnt] = 0;
730 }
732 trace_registered = 0;
734 return gator_events_install(&gator_events_mali_interface);
735 }
737 gator_events_init(gator_events_mali_init);