summaryrefslogtreecommitdiffstats
path: root/driver
diff options
context:
space:
mode:
Diffstat (limited to 'driver')
-rw-r--r--driver/Makefile7
-rw-r--r--driver/gator_annotate.c9
-rw-r--r--driver/gator_cookies.c5
-rw-r--r--driver/gator_ebs.c18
-rw-r--r--[-rwxr-xr-x]driver/gator_events_mali_400.c (renamed from driver/gator_events_mali.c)341
-rw-r--r--driver/gator_events_mali_400.h19
-rw-r--r--driver/gator_events_mali_common.c79
-rw-r--r--driver/gator_events_mali_common.h85
-rw-r--r--driver/gator_events_mali_t6xx.c553
-rw-r--r--driver/gator_events_mali_t6xx_hw.c571
-rw-r--r--driver/gator_events_meminfo.c5
-rw-r--r--driver/gator_events_net.c1
-rw-r--r--[-rwxr-xr-x]driver/gator_events_perf_pmu.c20
-rw-r--r--driver/gator_fs.c1
-rw-r--r--[-rwxr-xr-x]driver/gator_hrtimer_gator.c0
-rw-r--r--driver/gator_main.c19
-rw-r--r--[-rwxr-xr-x]driver/gator_marshaling.c0
-rw-r--r--driver/gator_trace_gpu.c152
-rw-r--r--[-rwxr-xr-x]driver/gator_trace_power.c0
-rw-r--r--driver/mali_t6xx.mk24
20 files changed, 1675 insertions, 234 deletions
diff --git a/driver/Makefile b/driver/Makefile
index 667637e..025dd9e 100644
--- a/driver/Makefile
+++ b/driver/Makefile
@@ -17,10 +17,13 @@ gator-y += gator_events_mmaped.o
17 17
18ifneq ($(GATOR_WITH_MALI_SUPPORT),) 18ifneq ($(GATOR_WITH_MALI_SUPPORT),)
19ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_T6xx) 19ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_T6xx)
20gator-y += gator_events_mali_t6xx.o 20gator-y += gator_events_mali_t6xx.o \
21 gator_events_mali_t6xx_hw.o
22include $(M)/mali_t6xx.mk
21else 23else
22gator-y += gator_events_mali.o 24gator-y += gator_events_mali_400.o
23endif 25endif
26gator-y += gator_events_mali_common.o
24EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT) 27EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT)
25endif 28endif
26 29
diff --git a/driver/gator_annotate.c b/driver/gator_annotate.c
index b2288b3..b444789 100644
--- a/driver/gator_annotate.c
+++ b/driver/gator_annotate.c
@@ -43,9 +43,9 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t
43 if (*offset) 43 if (*offset)
44 return -EINVAL; 44 return -EINVAL;
45 45
46 if (!collect_annotations) { 46 if (!collect_annotations)
47 // Not collecting annotations, tell the caller everything was written
47 return count_orig; 48 return count_orig;
48 }
49 49
50 cpu = 0; // Annotation only uses a single per-cpu buffer as the data must be in order to the engine 50 cpu = 0; // Annotation only uses a single per-cpu buffer as the data must be in order to the engine
51 51
@@ -64,6 +64,8 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t
64 size = count < available ? count : available; 64 size = count < available ? count : available;
65 65
66 if (size <= 0) { 66 if (size <= 0) {
67 // Buffer is full but don't return an error. Instead return 0 so the
68 // caller knows nothing was written and they can try again.
67 size = 0; 69 size = 0;
68 goto annotate_write_out; 70 goto annotate_write_out;
69 } 71 }
@@ -115,8 +117,9 @@ static int annotate_release(struct inode *inode, struct file *file)
115 // synchronize between cores 117 // synchronize between cores
116 spin_lock(&annotate_lock); 118 spin_lock(&annotate_lock);
117 119
118 if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF] && buffer_check_space(cpu, ANNOTATE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) { 120 if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF] && buffer_check_space(cpu, ANNOTATE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
119 uint32_t tid = current->pid; 121 uint32_t tid = current->pid;
122 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id());
120 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, tid); 123 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, tid);
121 gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); // time 124 gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); // time
122 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); // size 125 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); // size
diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c
index df14d09..d7d8e84 100644
--- a/driver/gator_cookies.c
+++ b/driver/gator_cookies.c
@@ -27,8 +27,6 @@ static void wq_cookie_handler(struct work_struct *unused);
27DECLARE_WORK(cookie_work, wq_cookie_handler); 27DECLARE_WORK(cookie_work, wq_cookie_handler);
28static struct timer_list app_process_wake_up_timer; 28static struct timer_list app_process_wake_up_timer;
29static void app_process_wake_up_handler(unsigned long unused_data); 29static void app_process_wake_up_handler(unsigned long unused_data);
30static struct timer_list app_process_wake_up_timer;
31static void app_process_wake_up_handler(unsigned long unused_data);
32 30
33static uint32_t cookiemap_code(uint64_t value64) { 31static uint32_t cookiemap_code(uint64_t value64) {
34 uint32_t value = (uint32_t)((value64 >> 32) + value64); 32 uint32_t value = (uint32_t)((value64 >> 32) + value64);
@@ -172,6 +170,7 @@ static int translate_app_process(char** text, int cpu, struct task_struct * task
172 170
173 translate_buffer_write_int(cpu, (unsigned int)task); 171 translate_buffer_write_int(cpu, (unsigned int)task);
174 translate_buffer_write_int(cpu, (unsigned int)vma); 172 translate_buffer_write_int(cpu, (unsigned int)vma);
173
175 mod_timer(&app_process_wake_up_timer, jiffies + 1); 174 mod_timer(&app_process_wake_up_timer, jiffies + 1);
176 goto out; 175 goto out;
177 } 176 }
@@ -382,7 +381,7 @@ static int cookies_initialize(void)
382 gator_crc32_table[i] = crc; 381 gator_crc32_table[i] = crc;
383 } 382 }
384 383
385 setup_timer(&app_process_wake_up_timer, app_process_wake_up_handler, 0); 384 setup_timer(&app_process_wake_up_timer, app_process_wake_up_handler, 0);
386 385
387cookie_setup_error: 386cookie_setup_error:
388 return err; 387 return err;
diff --git a/driver/gator_ebs.c b/driver/gator_ebs.c
index 1208d69..6abdfa4 100644
--- a/driver/gator_ebs.c
+++ b/driver/gator_ebs.c
@@ -23,10 +23,8 @@ extern unsigned long pmnc_event[];
23extern unsigned long pmnc_count[]; 23extern unsigned long pmnc_count[];
24extern unsigned long pmnc_key[]; 24extern unsigned long pmnc_key[];
25 25
26static DEFINE_PER_CPU(struct perf_event *, pevent);
27static DEFINE_PER_CPU(struct perf_event_attr *, pevent_attr); 26static DEFINE_PER_CPU(struct perf_event_attr *, pevent_attr);
28static DEFINE_PER_CPU(int, key); 27static DEFINE_PER_CPU(int, key);
29static DEFINE_PER_CPU(unsigned int, prev_value);
30 28
31#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) 29#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
32static void ebs_overflow_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs) 30static void ebs_overflow_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs)
@@ -36,7 +34,7 @@ static void ebs_overflow_handler(struct perf_event *event, struct perf_sample_da
36{ 34{
37 int cpu = smp_processor_id(); 35 int cpu = smp_processor_id();
38 36
39 if (event != per_cpu(pevent, cpu)) 37 if (event != per_cpu(pevent_ebs, cpu))
40 return; 38 return;
41 39
42 // Output backtrace 40 // Output backtrace
@@ -54,9 +52,9 @@ static void gator_event_sampling_online_dispatch(int cpu)
54 return; 52 return;
55 53
56#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) 54#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
57 ev = per_cpu(pevent, cpu) = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu), cpu, 0, ebs_overflow_handler); 55 ev = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu), cpu, 0, ebs_overflow_handler);
58#else 56#else
59 ev = per_cpu(pevent, cpu) = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu), cpu, 0, ebs_overflow_handler, 0); 57 ev = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu), cpu, 0, ebs_overflow_handler, 0);
60#endif 58#endif
61 59
62 if (IS_ERR(ev)) { 60 if (IS_ERR(ev)) {
@@ -71,7 +69,7 @@ static void gator_event_sampling_online_dispatch(int cpu)
71 } 69 }
72 70
73 ev->pmu->read(ev); 71 ev->pmu->read(ev);
74 per_cpu(prev_value, cpu) = local64_read(&ev->count); 72 per_cpu(pevent_ebs, cpu) = ev;
75} 73}
76 74
77static void gator_event_sampling_offline_dispatch(int cpu) 75static void gator_event_sampling_offline_dispatch(int cpu)
@@ -79,9 +77,9 @@ static void gator_event_sampling_offline_dispatch(int cpu)
79 struct perf_event * pe = NULL; 77 struct perf_event * pe = NULL;
80 78
81 mutex_lock(&perf_mutex); 79 mutex_lock(&perf_mutex);
82 if (per_cpu(pevent, cpu)) { 80 if (per_cpu(pevent_ebs, cpu)) {
83 pe = per_cpu(pevent, cpu); 81 pe = per_cpu(pevent_ebs, cpu);
84 per_cpu(pevent, cpu) = NULL; 82 per_cpu(pevent_ebs, cpu) = NULL;
85 } 83 }
86 mutex_unlock(&perf_mutex); 84 mutex_unlock(&perf_mutex);
87 85
@@ -95,7 +93,7 @@ static int gator_event_sampling_start(void)
95 int cnt, event = 0, count = 0, ebs_key = 0, cpu; 93 int cnt, event = 0, count = 0, ebs_key = 0, cpu;
96 94
97 for_each_present_cpu(cpu) { 95 for_each_present_cpu(cpu) {
98 per_cpu(pevent, cpu) = NULL; 96 per_cpu(pevent_ebs, cpu) = NULL;
99 per_cpu(pevent_attr, cpu) = NULL; 97 per_cpu(pevent_attr, cpu) = NULL;
100 } 98 }
101 99
diff --git a/driver/gator_events_mali.c b/driver/gator_events_mali_400.c
index e3b6e13..ef4cc58 100755..100644
--- a/driver/gator_events_mali.c
+++ b/driver/gator_events_mali_400.c
@@ -14,13 +14,8 @@
14 14
15#include "linux/mali_linux_trace.h" 15#include "linux/mali_linux_trace.h"
16 16
17#if !defined(GATOR_MALI_INTERFACE_STYLE) 17#include "gator_events_mali_common.h"
18/* 18#include "gator_events_mali_400.h"
19 * At the moment, we only have users with the old style interface, so
20 * make our life easier by making it the default...
21 */
22#define GATOR_MALI_INTERFACE_STYLE (2)
23#endif
24 19
25/* 20/*
26 * There are (currently) three different variants of the comms between gator and Mali: 21 * There are (currently) three different variants of the comms between gator and Mali:
@@ -35,11 +30,6 @@
35#define GATOR_MALI_INTERFACE_STYLE (3) 30#define GATOR_MALI_INTERFACE_STYLE (3)
36#endif 31#endif
37 32
38#define MALI_200 (0x0a07)
39#define MALI_300 (0x0b06) //This is not actually true; Mali-300 is also 0x0b07
40#define MALI_400 (0x0b07)
41#define MALI_T6xx (0x0056)
42
43/* 33/*
44 * List of possible actions allowing DDK to be controlled by Streamline. 34 * List of possible actions allowing DDK to be controlled by Streamline.
45 * The following numbers are used by DDK to control the frame buffer dumping. 35 * The following numbers are used by DDK to control the frame buffer dumping.
@@ -52,13 +42,14 @@
52/* 42/*
53 * Check that the MALI_SUPPORT define is set to one of the allowable device codes. 43 * Check that the MALI_SUPPORT define is set to one of the allowable device codes.
54 */ 44 */
55#if !defined(MALI_SUPPORT) 45#if (MALI_SUPPORT != MALI_400)
56#error MALI_SUPPORT not defined! 46#error MALI_SUPPORT set to an invalid device code: expecting MALI_400
57#elif (MALI_SUPPORT != MALI_200) && (MALI_SUPPORT != MALI_300) && (MALI_SUPPORT != MALI_400) && (MALI_SUPPORT != MALI_T6xx)
58#error MALI_SUPPORT set to an invalid device code
59#endif 47#endif
60 48
61static const char *mali_name; 49/*
50 * The number of fragment processors. Update to suit your hardware implementation.
51 */
52#define NUM_FP_UNITS (4)
62 53
63enum counters { 54enum counters {
64 /* Timeline activity */ 55 /* Timeline activity */
@@ -131,7 +122,9 @@ enum counters {
131 COUNTER_GLES_STRIP_LINES_COUNT, 122 COUNTER_GLES_STRIP_LINES_COUNT,
132 COUNTER_GLES_LOOP_LINES_COUNT, 123 COUNTER_GLES_LOOP_LINES_COUNT,
133 124
134 COUNTER_FILMSTRIP, 125 COUNTER_FILMSTRIP,
126 COUNTER_FREQUENCY,
127 COUNTER_VOLTAGE,
135 128
136 NUMBER_OF_EVENTS 129 NUMBER_OF_EVENTS
137}; 130};
@@ -146,7 +139,7 @@ enum counters {
146#define LAST_SW_COUNTER COUNTER_GLES_LOOP_LINES_COUNT 139#define LAST_SW_COUNTER COUNTER_GLES_LOOP_LINES_COUNT
147 140
148#define FIRST_SPECIAL_COUNTER COUNTER_FILMSTRIP 141#define FIRST_SPECIAL_COUNTER COUNTER_FILMSTRIP
149#define LAST_SPECIAL_COUNTER COUNTER_FILMSTRIP 142#define LAST_SPECIAL_COUNTER COUNTER_VOLTAGE
150 143
151/* gatorfs variables for counter enable state, 144/* gatorfs variables for counter enable state,
152 * the event the counter should count and the 145 * the event the counter should count and the
@@ -176,13 +169,13 @@ static int trace_registered;
176 */ 169 */
177static u32 get_difference(u32 start, u32 end) 170static u32 get_difference(u32 start, u32 end)
178{ 171{
179 if (start - end >= 0) 172 if (start - end >= 0)
180 { 173 {
181 return start - end; 174 return start - end;
182 } 175 }
183 176
184 // Mali counters are unsigned 32 bit values that wrap. 177 // Mali counters are unsigned 32 bit values that wrap.
185 return (4294967295u - end) + start; 178 return (4294967295u - end) + start;
186} 179}
187 180
188/** 181/**
@@ -202,6 +195,7 @@ static inline int is_hw_counter(unsigned int event_id)
202 return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER); 195 return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER);
203} 196}
204 197
198#if GATOR_MALI_INTERFACE_STYLE == 2
205/** 199/**
206 * Returns non-zero if the given counter ID is a software counter. 200 * Returns non-zero if the given counter ID is a software counter.
207 */ 201 */
@@ -209,7 +203,9 @@ static inline int is_sw_counter(unsigned int event_id)
209{ 203{
210 return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER); 204 return (event_id >= FIRST_SW_COUNTER && event_id <= LAST_SW_COUNTER);
211} 205}
206#endif
212 207
208#if GATOR_MALI_INTERFACE_STYLE == 2
213/* 209/*
214 * The Mali DDK uses s64 types to contain software counter values, but gator 210 * The Mali DDK uses s64 types to contain software counter values, but gator
215 * can only use a maximum of 32 bits. This function scales a software counter 211 * can only use a maximum of 32 bits. This function scales a software counter
@@ -231,6 +227,7 @@ static u32 scale_sw_counter_value(unsigned int event_id, signed long long value)
231 227
232 return scaled_value; 228 return scaled_value;
233} 229}
230#endif
234 231
235/* Probe for continuously sampled counter */ 232/* Probe for continuously sampled counter */
236#if 0 //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING 233#if 0 //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING
@@ -271,33 +268,25 @@ GATOR_DEFINE_PROBE(mali_sw_counter, TP_PROTO(unsigned int event_id, signed long
271#if GATOR_MALI_INTERFACE_STYLE == 3 268#if GATOR_MALI_INTERFACE_STYLE == 3
272GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void * surface_id, unsigned int * counters)) 269GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void * surface_id, unsigned int * counters))
273{ 270{
274 u32 i; 271 u32 i;
275
276 /* Copy over the values for those counters which are enabled. */
277 for(i=FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++)
278 {
279 if(counter_enabled[i])
280 {
281 counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]);
282 }
283 }
284}
285#endif /* GATOR_MALI_INTERFACE_STYLE == 3 */
286 272
287//TODO need to work out how many fp units we have 273 /* Copy over the values for those counters which are enabled. */
288u32 gator_mali_get_n_fp(void) { 274 for(i=FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++)
289 return 4; 275 {
290} 276 if(counter_enabled[i])
291 277 {
292//TODO need to work out what kind of Mali we are looking at 278 counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]);
293u32 gator_mali_get_id(void) { 279 }
294 return MALI_SUPPORT; 280 }
295} 281}
282#endif /* GATOR_MALI_INTERFACE_STYLE == 3 */
296 283
297int gator_events_mali_create_files(struct super_block *sb, struct dentry *root) { 284static int create_files(struct super_block *sb, struct dentry *root) {
298 struct dentry *dir; 285 struct dentry *dir;
299 int event; 286 int event;
300 int n_fp = gator_mali_get_n_fp(); 287 int n_fp = NUM_FP_UNITS;
288
289 const char* mali_name = gator_mali_get_mali_name();
301 290
302 /* 291 /*
303 * Create the filesystem entries for vertex processor, fragement processor 292 * Create the filesystem entries for vertex processor, fragement processor
@@ -389,12 +378,27 @@ int gator_events_mali_create_files(struct super_block *sb, struct dentry *root)
389 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]); 378 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
390 } 379 }
391 380
392 /* Now set up the special counter entries */ 381 /* Now set up the special counter entries */
393 for (event = FIRST_SPECIAL_COUNTER; event <= LAST_SPECIAL_COUNTER; event++) 382 for (event = FIRST_SPECIAL_COUNTER; event <= LAST_SPECIAL_COUNTER; event++)
394 { 383 {
395 char buf[40]; 384 char buf[40];
396 385
397 snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip", mali_name); 386 switch(event) {
387 case COUNTER_FILMSTRIP:
388 snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip", mali_name);
389 break;
390
391 case COUNTER_FREQUENCY:
392 snprintf(buf, sizeof(buf), "ARM_%s_Frequency", mali_name);
393 break;
394
395 case COUNTER_VOLTAGE:
396 snprintf(buf, sizeof(buf), "ARM_%s_Voltage", mali_name);
397 break;
398
399 default:
400 break;
401 }
398 402
399 dir = gatorfs_mkdir(sb, root, buf); 403 dir = gatorfs_mkdir(sb, root, buf);
400 404
@@ -407,17 +411,14 @@ int gator_events_mali_create_files(struct super_block *sb, struct dentry *root)
407 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]); 411 gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]);
408 } 412 }
409 413
410
411 return 0; 414 return 0;
412} 415}
413 416
414//TODO 417/*
415void _mali_profiling_set_event(unsigned int, unsigned int); 418 * Local store for the get_counters entry point into the DDK.
416void _mali_osk_fb_control_set(unsigned int, unsigned int); 419 * This is stored here since it is used very regularly.
417void _mali_profiling_control(unsigned int, unsigned int); 420 */
418 421static mali_profiling_get_counters_type *mali_get_counters = NULL;
419void _mali_profiling_get_counters(unsigned int*, unsigned int*, unsigned int*, unsigned int*);
420void (*_mali_profiling_get_counters_function_pointer)(unsigned int*, unsigned int*, unsigned int*, unsigned int*);
421 422
422/* 423/*
423 * Examine list of software counters and determine if any one is enabled. 424 * Examine list of software counters and determine if any one is enabled.
@@ -425,17 +426,17 @@ void (*_mali_profiling_get_counters_function_pointer)(unsigned int*, unsigned in
425 */ 426 */
426static int is_any_sw_counter_enabled(void) 427static int is_any_sw_counter_enabled(void)
427{ 428{
428 unsigned int i; 429 unsigned int i;
429 430
430 for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) 431 for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++)
431 { 432 {
432 if (counter_enabled[i]) 433 if (counter_enabled[i])
433 { 434 {
434 return 1; /* At least one counter is enabled */ 435 return 1; /* At least one counter is enabled */
435 } 436 }
436 } 437 }
437 438
438 return 0; /* No s/w counters enabled */ 439 return 0; /* No s/w counters enabled */
439} 440}
440 441
441static void mali_counter_initialize(void) 442static void mali_counter_initialize(void)
@@ -444,22 +445,22 @@ static void mali_counter_initialize(void)
444 * then we can request the HW counters (of which there are only 2) 445 * then we can request the HW counters (of which there are only 2)
445 * be configured to count the desired events 446 * be configured to count the desired events
446 */ 447 */
447 void (*set_hw_event)(unsigned int, unsigned int); 448 mali_profiling_set_event_type *mali_set_hw_event;
448 void (*set_fb_event)(unsigned int, unsigned int); 449 mali_osk_fb_control_set_type *mali_set_fb_event;
449 void (*mali_control)(unsigned int, unsigned int); 450 mali_profiling_control_type *mali_control;
450 451
451 set_hw_event = symbol_get(_mali_profiling_set_event); 452 mali_set_hw_event = symbol_get(_mali_profiling_set_event);
452 453
453 if (set_hw_event) { 454 if (mali_set_hw_event) {
454 int i; 455 int i;
455 456
456 pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n",set_hw_event); 457 pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n",mali_set_hw_event);
457 458
458 for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) { 459 for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
459 if (counter_enabled[i]) { 460 if (counter_enabled[i]) {
460 set_hw_event(i, counter_event[i]); 461 mali_set_hw_event(i, counter_event[i]);
461 } else { 462 } else {
462 set_hw_event(i, 0xFFFFFFFF); 463 mali_set_hw_event(i, 0xFFFFFFFF);
463 } 464 }
464 } 465 }
465 466
@@ -468,64 +469,64 @@ static void mali_counter_initialize(void)
468 printk("gator: mali online _mali_profiling_set_event symbol not found\n"); 469 printk("gator: mali online _mali_profiling_set_event symbol not found\n");
469 } 470 }
470 471
471 set_fb_event = symbol_get(_mali_osk_fb_control_set); 472 mali_set_fb_event = symbol_get(_mali_osk_fb_control_set);
472 473
473 if (set_fb_event) { 474 if (mali_set_fb_event) {
474 pr_debug("gator: mali online _mali_osk_fb_control_set symbol @ %p\n", set_fb_event); 475 pr_debug("gator: mali online _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
475 476
476 set_fb_event(0,(counter_enabled[COUNTER_FILMSTRIP]?1:0)); 477 mali_set_fb_event(0,(counter_enabled[COUNTER_FILMSTRIP]?1:0));
477 478
478 symbol_put(_mali_osk_fb_control_set); 479 symbol_put(_mali_osk_fb_control_set);
479 } else { 480 } else {
480 printk("gator: mali online _mali_osk_fb_control_set symbol not found\n"); 481 printk("gator: mali online _mali_osk_fb_control_set symbol not found\n");
481 } 482 }
482 483
483 /* Generic control interface for Mali DDK. */ 484 /* Generic control interface for Mali DDK. */
484 mali_control = symbol_get(_mali_profiling_control); 485 mali_control = symbol_get(_mali_profiling_control);
485 if (mali_control) { 486 if (mali_control) {
486 /* The event attribute in the XML file keeps the actual frame rate. */ 487 /* The event attribute in the XML file keeps the actual frame rate. */
487 unsigned int rate = counter_event[COUNTER_FILMSTRIP] & 0xff; 488 unsigned int rate = counter_event[COUNTER_FILMSTRIP] & 0xff;
488 unsigned int resize_factor = (counter_event[COUNTER_FILMSTRIP] >> 8) & 0xff; 489 unsigned int resize_factor = (counter_event[COUNTER_FILMSTRIP] >> 8) & 0xff;
489 490
490 pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control); 491 pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control);
491 492
492 mali_control(SW_EVENTS_ENABLE, (is_any_sw_counter_enabled()?1:0)); 493 mali_control(SW_EVENTS_ENABLE, (is_any_sw_counter_enabled()?1:0));
493 mali_control(FBDUMP_CONTROL_ENABLE, (counter_enabled[COUNTER_FILMSTRIP]?1:0)); 494 mali_control(FBDUMP_CONTROL_ENABLE, (counter_enabled[COUNTER_FILMSTRIP]?1:0));
494 mali_control(FBDUMP_CONTROL_RATE, rate); 495 mali_control(FBDUMP_CONTROL_RATE, rate);
495 mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor); 496 mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor);
496 497
497 pr_debug("gator: sent mali_control enabled=%d, rate=%d\n", (counter_enabled[COUNTER_FILMSTRIP]?1:0), rate); 498 pr_debug("gator: sent mali_control enabled=%d, rate=%d\n", (counter_enabled[COUNTER_FILMSTRIP]?1:0), rate);
498 499
499 symbol_put(_mali_profiling_control); 500 symbol_put(_mali_profiling_control);
500 } else { 501 } else {
501 printk("gator: mali online _mali_profiling_control symbol not found\n"); 502 printk("gator: mali online _mali_profiling_control symbol not found\n");
502 } 503 }
503 504
504 _mali_profiling_get_counters_function_pointer = symbol_get(_mali_profiling_get_counters); 505 mali_get_counters = symbol_get(_mali_profiling_get_counters);
505 if (_mali_profiling_get_counters_function_pointer){ 506 if (mali_get_counters){
506 pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", _mali_profiling_get_counters_function_pointer); 507 pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", mali_get_counters);
507 counter_prev[COUNTER_L2_C0] = 0; 508 counter_prev[COUNTER_L2_C0] = 0;
508 counter_prev[COUNTER_L2_C1] = 0; 509 counter_prev[COUNTER_L2_C1] = 0;
509 } 510 }
510 else{ 511 else{
511 pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined"); 512 pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined");
512 } 513 }
513} 514}
514 515
515static void mali_counter_deinitialize(void) 516static void mali_counter_deinitialize(void)
516{ 517{
517 void (*set_hw_event)(unsigned int, unsigned int); 518 mali_profiling_set_event_type *mali_set_hw_event;
518 void (*set_fb_event)(unsigned int, unsigned int); 519 mali_osk_fb_control_set_type *mali_set_fb_event;
519 void (*mali_control)(unsigned int, unsigned int); 520 mali_profiling_control_type *mali_control;
520 521
521 set_hw_event = symbol_get(_mali_profiling_set_event); 522 mali_set_hw_event = symbol_get(_mali_profiling_set_event);
522 523
523 if (set_hw_event) { 524 if (mali_set_hw_event) {
524 int i; 525 int i;
525 526
526 pr_debug("gator: mali offline _mali_profiling_set_event symbol @ %p\n",set_hw_event); 527 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 for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) {
528 set_hw_event(i, 0xFFFFFFFF); 529 mali_set_hw_event(i, 0xFFFFFFFF);
529 } 530 }
530 531
531 symbol_put(_mali_profiling_set_event); 532 symbol_put(_mali_profiling_set_event);
@@ -533,41 +534,41 @@ static void mali_counter_deinitialize(void)
533 printk("gator: mali offline _mali_profiling_set_event symbol not found\n"); 534 printk("gator: mali offline _mali_profiling_set_event symbol not found\n");
534 } 535 }
535 536
536 set_fb_event = symbol_get(_mali_osk_fb_control_set); 537 mali_set_fb_event = symbol_get(_mali_osk_fb_control_set);
537 538
538 if (set_fb_event) { 539 if (mali_set_fb_event) {
539 pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", set_fb_event); 540 pr_debug("gator: mali offline _mali_osk_fb_control_set symbol @ %p\n", mali_set_fb_event);
540 541
541 set_fb_event(0,0); 542 mali_set_fb_event(0,0);
543
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 }
542 548
543 symbol_put(_mali_osk_fb_control_set); 549 /* Generic control interface for Mali DDK. */
544 } else { 550 mali_control = symbol_get(_mali_profiling_control);
545 printk("gator: mali offline _mali_osk_fb_control_set symbol not found\n");
546 }
547
548 /* Generic control interface for Mali DDK. */
549 mali_control = symbol_get(_mali_profiling_control);
550 551
551 if (mali_control) { 552 if (mali_control) {
552 pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", set_fb_event); 553 pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_set_fb_event);
553 554
554 /* Reset the DDK state - disable counter collection */ 555 /* Reset the DDK state - disable counter collection */
555 mali_control(SW_EVENTS_ENABLE, 0); 556 mali_control(SW_EVENTS_ENABLE, 0);
556 557
557 mali_control(FBDUMP_CONTROL_ENABLE, 0); 558 mali_control(FBDUMP_CONTROL_ENABLE, 0);
558 559
559 symbol_put(_mali_profiling_control); 560 symbol_put(_mali_profiling_control);
560 } else { 561 } else {
561 printk("gator: mali offline _mali_profiling_control symbol not found\n"); 562 printk("gator: mali offline _mali_profiling_control symbol not found\n");
562 } 563 }
563 564
564 if (_mali_profiling_get_counters_function_pointer){ 565 if (mali_get_counters){
565 symbol_put(_mali_profiling_get_counters); 566 symbol_put(_mali_profiling_get_counters);
566 } 567 }
567 568
568} 569}
569 570
570static int gator_events_mali_start(void) { 571static int start(void) {
571 // register tracepoints 572 // register tracepoints
572 if (GATOR_REGISTER_TRACE(mali_hw_counter)) { 573 if (GATOR_REGISTER_TRACE(mali_hw_counter)) {
573 printk("gator: mali_hw_counter tracepoint failed to activate\n"); 574 printk("gator: mali_hw_counter tracepoint failed to activate\n");
@@ -575,9 +576,9 @@ static int gator_events_mali_start(void) {
575 } 576 }
576 577
577#if GATOR_MALI_INTERFACE_STYLE == 1 578#if GATOR_MALI_INTERFACE_STYLE == 1
578 /* None. */ 579 /* None. */
579#elif GATOR_MALI_INTERFACE_STYLE == 2 580#elif GATOR_MALI_INTERFACE_STYLE == 2
580 /* For patched Mali driver. */ 581 /* For patched Mali driver. */
581 if (GATOR_REGISTER_TRACE(mali_sw_counter)) { 582 if (GATOR_REGISTER_TRACE(mali_sw_counter)) {
582 printk("gator: mali_sw_counter tracepoint failed to activate\n"); 583 printk("gator: mali_sw_counter tracepoint failed to activate\n");
583 return -1; 584 return -1;
@@ -598,7 +599,7 @@ static int gator_events_mali_start(void) {
598 return 0; 599 return 0;
599} 600}
600 601
601static void gator_events_mali_stop(void) { 602static void stop(void) {
602 unsigned int cnt; 603 unsigned int cnt;
603 604
604 pr_debug("gator: mali stop\n"); 605 pr_debug("gator: mali stop\n");
@@ -632,7 +633,7 @@ static void gator_events_mali_stop(void) {
632 mali_counter_deinitialize(); 633 mali_counter_deinitialize();
633} 634}
634 635
635static int gator_events_mali_read(int **buffer) { 636static int read(int **buffer) {
636 int cnt, len = 0; 637 int cnt, len = 0;
637 638
638 if (smp_processor_id()) return 0; 639 if (smp_processor_id()) return 0;
@@ -645,8 +646,8 @@ static int gator_events_mali_read(int **buffer) {
645 u32 val1 = 0; 646 u32 val1 = 0;
646 647
647 // Poke the driver to get the counter values 648 // Poke the driver to get the counter values
648 if (_mali_profiling_get_counters_function_pointer){ 649 if (mali_get_counters){
649 _mali_profiling_get_counters_function_pointer(&src0, &val0, &src1, &val1); 650 mali_get_counters(&src0, &val0, &src1, &val1);
650 } 651 }
651 652
652 if (counter_enabled[COUNTER_L2_C0]) 653 if (counter_enabled[COUNTER_L2_C0])
@@ -678,6 +679,23 @@ static int gator_events_mali_read(int **buffer) {
678 } 679 }
679 } 680 }
680 681
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 }
691
692 cnt = COUNTER_VOLTAGE;
693 if (counter_enabled[cnt]) {
694 counter_dump[len++] = counter_key[cnt];
695 counter_dump[len++] = counter_data[cnt];
696 }
697
698
681 if (buffer) { 699 if (buffer) {
682 *buffer = (int*) counter_dump; 700 *buffer = (int*) counter_dump;
683 } 701 }
@@ -686,34 +704,20 @@ static int gator_events_mali_read(int **buffer) {
686} 704}
687 705
688static struct gator_interface gator_events_mali_interface = { 706static struct gator_interface gator_events_mali_interface = {
689 .create_files = gator_events_mali_create_files, 707 .create_files = create_files,
690 .start = gator_events_mali_start, 708 .start = start,
691 .stop = gator_events_mali_stop, 709 .stop = stop,
692 .read = gator_events_mali_read, 710 .read = read,
693}; 711};
694 712
713extern 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}
717
695int gator_events_mali_init(void) 718int gator_events_mali_init(void)
696{ 719{
697 unsigned int cnt; 720 unsigned int cnt;
698 u32 id = gator_mali_get_id();
699
700 switch (id) {
701 case MALI_T6xx:
702 mali_name = "Mali-T6xx";
703 break;
704 case MALI_400:
705 mali_name = "Mali-400";
706 break;
707 case MALI_300:
708 mali_name = "Mali-300";
709 break;
710 case MALI_200:
711 mali_name = "Mali-200";
712 break;
713 default:
714 printk("Unknown Mali ID (%d)\n", id);
715 return -1;
716 }
717 721
718 pr_debug("gator: mali init\n"); 722 pr_debug("gator: mali init\n");
719 723
@@ -722,11 +726,12 @@ int gator_events_mali_init(void)
722 counter_event[cnt] = 0; 726 counter_event[cnt] = 0;
723 counter_key[cnt] = gator_events_get_key(); 727 counter_key[cnt] = gator_events_get_key();
724 counter_address[cnt] = NULL; 728 counter_address[cnt] = NULL;
725 counter_data[cnt] = 0; 729 counter_data[cnt] = 0;
726 } 730 }
727 731
728 trace_registered = 0; 732 trace_registered = 0;
729 733
730 return gator_events_install(&gator_events_mali_interface); 734 return gator_events_install(&gator_events_mali_interface);
731} 735}
736
732gator_events_init(gator_events_mali_init); 737gator_events_init(gator_events_mali_init);
diff --git a/driver/gator_events_mali_400.h b/driver/gator_events_mali_400.h
new file mode 100644
index 0000000..b784ae9
--- /dev/null
+++ b/driver/gator_events_mali_400.h
@@ -0,0 +1,19 @@
1/*
2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2011-2012 ARM Limited
5 * ALL RIGHTS RESERVED
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
9 */
10
11/*
12 * Header contains common definitions for the Mali-400 processors.
13 */
14#if !defined(GATOR_EVENTS_MALI_400_H)
15#define GATOR_EVENTS_MALI_400_H
16
17extern void gator_events_mali_log_dvfs_event(unsigned int d0, unsigned int d1);
18
19#endif /* GATOR_EVENTS_MALI_400_H */
diff --git a/driver/gator_events_mali_common.c b/driver/gator_events_mali_common.c
new file mode 100644
index 0000000..2dd9ad6
--- /dev/null
+++ b/driver/gator_events_mali_common.c
@@ -0,0 +1,79 @@
1/*
2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2011-2012 ARM Limited
5 * ALL RIGHTS RESERVED
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
9 */
10#include "gator_events_mali_common.h"
11
12static u32 gator_mali_get_id(void)
13{
14 return MALI_SUPPORT;
15}
16
17extern const char* gator_mali_get_mali_name(void)
18{
19 u32 id = gator_mali_get_id();
20
21 switch (id) {
22 case MALI_T6xx:
23 return "Mali-T6xx";
24 case MALI_400:
25 return "Mali-400";
26 default:
27 pr_debug("gator: Mali-T6xx: unknown Mali ID (%d)\n", id);
28 return "Mali-Unknown";
29 }
30}
31
32extern int gator_mali_create_file_system(const char* mali_name, const char* event_name, struct super_block *sb, struct dentry *root, mali_counter *counter)
33{
34 int err;
35 char buf[255];
36 struct dentry *dir;
37
38 /* If the counter name is empty ignore it*/
39 if (strlen(event_name) != 0)
40 {
41 /* Set up the filesystem entry for this event. */
42 snprintf(buf, sizeof(buf), "ARM_%s_%s", mali_name, event_name);
43
44 dir = gatorfs_mkdir(sb, root, buf);
45
46 if (dir == NULL)
47 {
48 pr_debug("gator: Mali-T6xx: error creating file system for: %s (%s)", event_name, buf);
49 return -1;
50 }
51
52 err = gatorfs_create_ulong(sb, dir, "enabled", &counter->enabled);
53 if (err != 0)
54 {
55 pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ulong for: %s (%s)", event_name, buf);
56 return -1;
57 }
58 err = gatorfs_create_ro_ulong(sb, dir, "key", &counter->key);
59 if (err != 0)
60 {
61 pr_debug("gator: Mali-T6xx: error calling gatorfs_create_ro_ulong for: %s (%s)", event_name, buf);
62 return -1;
63 }
64 }
65
66 return 0;
67}
68
69extern void gator_mali_initialise_counters(mali_counter counters[], unsigned int n_counters)
70{
71 unsigned int cnt;
72
73 for (cnt = 0; cnt < n_counters; cnt++) {
74 mali_counter *counter = &counters[cnt];
75
76 counter->key = gator_events_get_key();
77 counter->enabled = 0;
78 }
79}
diff --git a/driver/gator_events_mali_common.h b/driver/gator_events_mali_common.h
new file mode 100644
index 0000000..cb851d5
--- /dev/null
+++ b/driver/gator_events_mali_common.h
@@ -0,0 +1,85 @@
1/*
2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2011-2012 ARM Limited
5 * ALL RIGHTS RESERVED
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
9 */
10#if !defined(GATOR_EVENTS_MALI_COMMON_H)
11#define GATOR_EVENTS_MALI_COMMON_H
12
13#include "gator.h"
14
15#include <linux/module.h>
16#include <linux/time.h>
17#include <linux/math64.h>
18#include <linux/slab.h>
19#include <asm/io.h>
20
21/* Device codes for each known GPU */
22#define MALI_400 (0x0b07)
23#define MALI_T6xx (0x0056)
24
25/* Ensure that MALI_SUPPORT has been defined to something. */
26#ifndef MALI_SUPPORT
27#error MALI_SUPPORT not defined!
28#endif
29
30/* Values for the supported activity event types */
31#define ACTIVITY_START (1)
32#define ACTIVITY_STOP (2)
33
34/*
35 * Runtime state information for a counter.
36 */
37typedef struct {
38 unsigned long key; /* 'key' (a unique id set by gatord and returned by gator.ko) */
39 unsigned long enabled; /* counter enable state */
40} mali_counter;
41
42typedef void mali_profiling_set_event_type(unsigned int, unsigned int);
43typedef void mali_osk_fb_control_set_type(unsigned int, unsigned int);
44typedef void mali_profiling_control_type(unsigned int, unsigned int);
45typedef void mali_profiling_get_counters_type(unsigned int*, unsigned int*, unsigned int*, unsigned int*);
46
47/*
48 * Driver entry points for functions called directly by gator.
49 */
50extern void _mali_profiling_set_event(unsigned int, unsigned int);
51extern void _mali_osk_fb_control_set(unsigned int, unsigned int);
52extern void _mali_profiling_control(unsigned int, unsigned int);
53extern void _mali_profiling_get_counters(unsigned int*, unsigned int*, unsigned int*, unsigned int*);
54
55/**
56 * Returns a name which identifies the GPU type (eg Mali-400, Mali-T6xx).
57 *
58 * @return The name as a constant string.
59 */
60extern const char* gator_mali_get_mali_name(void);
61
62/**
63 * Creates a filesystem entry under /dev/gator relating to the specified event name and key, and
64 * associate the key/enable values with this entry point.
65 *
66 * @param mali_name A name related to the type of GPU, obtained from a call to gator_mali_get_mali_name()
67 * @param event_name The name of the event.
68 * @param sb Linux super block
69 * @param root Directory under which the entry will be created.
70 * @param counter_key Ptr to location which will be associated with the counter key.
71 * @param counter_enabled Ptr to location which will be associated with the counter enable state.
72 *
73 * @return 0 if entry point was created, non-zero if not.
74 */
75extern int gator_mali_create_file_system(const char* mali_name, const char* event_name, struct super_block *sb, struct dentry *root, mali_counter *counter);
76
77/**
78 * Initialises the counter array.
79 *
80 * @param keys The array of counters
81 * @param n_counters The number of entries in each of the arrays.
82 */
83extern void gator_mali_initialise_counters(mali_counter counters[], unsigned int n_counters);
84
85#endif /* GATOR_EVENTS_MALI_COMMON_H */
diff --git a/driver/gator_events_mali_t6xx.c b/driver/gator_events_mali_t6xx.c
new file mode 100644
index 0000000..79af764
--- /dev/null
+++ b/driver/gator_events_mali_t6xx.c
@@ -0,0 +1,553 @@
1/*
2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2011 ARM Limited
5 * ALL RIGHTS RESERVED
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
9 */
10
11#include "gator.h"
12
13#include <linux/module.h>
14#include <linux/time.h>
15#include <linux/math64.h>
16#include <linux/slab.h>
17#include <asm/io.h>
18
19#include "linux/mali_linux_trace.h"
20
21
22#include "gator_events_mali_common.h"
23
24/*
25 * Check that the MALI_SUPPORT define is set to one of the allowable device codes.
26 */
27#if (MALI_SUPPORT != MALI_T6xx)
28#error MALI_SUPPORT set to an invalid device code: expecting MALI_T6xx
29#endif
30
31
32/* Counters for Mali-T6xx:
33 *
34 * - Timeline events
35 * They are tracepoints, but instead of reporting a number they report a START/STOP event.
36 * They are reported in Streamline as number of microseconds while that particular counter was active.
37 *
38 * - SW counters
39 * They are tracepoints reporting a particular number.
40 * They are accumulated in sw_counter_data array until they are passed to Streamline, then they are zeroed.
41 *
42 * - Accumulators
43 * They are the same as software counters but their value is not zeroed.
44 */
45
46/* Timeline (start/stop) activity */
47static const char* timeline_event_names [] =
48{
49 "PM_SHADER_0",
50 "PM_SHADER_1",
51 "PM_SHADER_2",
52 "PM_SHADER_3",
53 "PM_SHADER_4",
54 "PM_SHADER_5",
55 "PM_SHADER_6",
56 "PM_SHADER_7",
57 "PM_TILER_0",
58 "PM_L2_0",
59 "PM_L2_1",
60 "MMU_AS_0",
61 "MMU_AS_1",
62 "MMU_AS_2",
63 "MMU_AS_3"
64};
65
66enum
67{
68 PM_SHADER_0 = 0,
69 PM_SHADER_1,
70 PM_SHADER_2,
71 PM_SHADER_3,
72 PM_SHADER_4,
73 PM_SHADER_5,
74 PM_SHADER_6,
75 PM_SHADER_7,
76 PM_TILER_0,
77 PM_L2_0,
78 PM_L2_1,
79 MMU_AS_0,
80 MMU_AS_1,
81 MMU_AS_2,
82 MMU_AS_3
83};
84/* The number of shader blocks in the enum above */
85#define NUM_PM_SHADER (8)
86
87/* Software Counters */
88static const char* software_counter_names [] =
89{
90 "MMU_PAGE_FAULT_0",
91 "MMU_PAGE_FAULT_1",
92 "MMU_PAGE_FAULT_2",
93 "MMU_PAGE_FAULT_3"
94};
95
96enum
97{
98 MMU_PAGE_FAULT_0 = 0,
99 MMU_PAGE_FAULT_1,
100 MMU_PAGE_FAULT_2,
101 MMU_PAGE_FAULT_3
102};
103
104/* Software Counters */
105static const char* accumulators_names [] =
106{
107 "TOTAL_ALLOC_PAGES"
108};
109
110enum
111{
112 TOTAL_ALLOC_PAGES = 0
113};
114
115#define FIRST_TIMELINE_EVENT (0)
116#define NUMBER_OF_TIMELINE_EVENTS (sizeof(timeline_event_names) / sizeof(timeline_event_names[0]))
117#define FIRST_SOFTWARE_COUNTER (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS)
118#define NUMBER_OF_SOFTWARE_COUNTERS (sizeof(software_counter_names) / sizeof(software_counter_names[0]))
119#define FIRST_ACCUMULATOR (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS)
120#define NUMBER_OF_ACCUMULATORS (sizeof(accumulators_names) / sizeof(accumulators_names[0]))
121#define NUMBER_OF_EVENTS (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS)
122
123/*
124 * gatorfs variables for counter enable state
125 */
126static mali_counter counters[NUMBER_OF_EVENTS];
127
128/* An array used to return the data we recorded
129 * as key,value pairs hence the *2
130 */
131static unsigned long counter_dump[NUMBER_OF_EVENTS * 2];
132
133/*
134 * Array holding counter start times (in ns) for each counter. A zero here
135 * indicates that the activity monitored by this counter is not running.
136 */
137static struct timespec timeline_event_starttime[NUMBER_OF_TIMELINE_EVENTS];
138
139/* The data we have recorded */
140static unsigned int timeline_data[NUMBER_OF_TIMELINE_EVENTS];
141static unsigned int sw_counter_data[NUMBER_OF_SOFTWARE_COUNTERS];
142static unsigned int accumulators_data[NUMBER_OF_ACCUMULATORS];
143
144/* Hold the previous timestamp, used to calculate the sample interval. */
145static struct timespec prev_timestamp;
146
147/**
148 * Returns the timespan (in microseconds) between the two specified timestamps.
149 *
150 * @param start Ptr to the start timestamp
151 * @param end Ptr to the end timestamp
152 *
153 * @return Number of microseconds between the two timestamps (can be negative if start follows end).
154 */
155static inline long get_duration_us(const struct timespec *start, const struct timespec *end)
156{
157 long event_duration_us = (end->tv_nsec - start->tv_nsec)/1000;
158 event_duration_us += (end->tv_sec - start->tv_sec) * 1000000;
159
160 return event_duration_us;
161}
162
163static void record_timeline_event(unsigned int timeline_index, unsigned int type)
164{
165 struct timespec event_timestamp;
166 struct timespec *event_start = &timeline_event_starttime[timeline_index];
167
168 switch(type)
169 {
170 case ACTIVITY_START:
171 /* Get the event time... */
172 getnstimeofday(&event_timestamp);
173
174 /* Remember the start time if the activity is not already started */
175 if(event_start->tv_sec == 0)
176 {
177 *event_start = event_timestamp; /* Structure copy */
178 }
179 break;
180
181 case ACTIVITY_STOP:
182 /* if the counter was started... */
183 if(event_start->tv_sec != 0)
184 {
185 /* Get the event time... */
186 getnstimeofday(&event_timestamp);
187
188 /* Accumulate the duration in us */
189 timeline_data[timeline_index] += get_duration_us(event_start, &event_timestamp);
190
191 /* Reset the start time to indicate the activity is stopped. */
192 event_start->tv_sec = 0;
193 }
194 break;
195
196 default:
197 /* Other activity events are ignored. */
198 break;
199 }
200}
201
202/*
203 * Documentation about the following tracepoints is in mali_linux_trace.h
204 */
205
206GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long long value))
207{
208#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */
209#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */
210#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */
211#define BIT_AT(value, pos) ((value >> pos) & 1)
212
213 static unsigned long long previous_shader_bitmask = 0;
214 static unsigned long long previous_tiler_bitmask = 0;
215 static unsigned long long previous_l2_bitmask = 0;
216
217 switch (event_id)
218 {
219 case SHADER_PRESENT_LO:
220 {
221 unsigned long long changed_bitmask = previous_shader_bitmask ^ value;
222 int pos;
223
224 for (pos = 0; pos < NUM_PM_SHADER; ++pos)
225 {
226 if (BIT_AT(changed_bitmask, pos))
227 {
228 record_timeline_event(PM_SHADER_0 + pos, BIT_AT(value, pos) ? ACTIVITY_START : ACTIVITY_STOP);
229 }
230 }
231
232 previous_shader_bitmask = value;
233 break;
234 }
235
236 case TILER_PRESENT_LO:
237 {
238 unsigned long long changed = previous_tiler_bitmask ^ value;
239
240 if (BIT_AT(changed, 0))
241 {
242 record_timeline_event(PM_TILER_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP);
243 }
244
245 previous_tiler_bitmask = value;
246 break;
247 }
248
249 case L2_PRESENT_LO:
250 {
251 unsigned long long changed = previous_l2_bitmask ^ value;
252
253 if (BIT_AT(changed, 0))
254 {
255 record_timeline_event(PM_L2_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP);
256 }
257 if (BIT_AT(changed, 4))
258 {
259 record_timeline_event(PM_L2_1, BIT_AT(value, 4) ? ACTIVITY_START : ACTIVITY_STOP);
260 }
261
262 previous_l2_bitmask = value;
263 break;
264 }
265
266 default:
267 /* No other blocks are supported at present */
268 break;
269 }
270
271#undef SHADER_PRESENT_LO
272#undef TILER_PRESENT_LO
273#undef L2_PRESENT_LO
274#undef BIT_AT
275}
276
277GATOR_DEFINE_PROBE(mali_page_fault_insert_pages, TP_PROTO(int event_id, unsigned long value))
278{
279 /* We add to the previous since we may receive many tracepoints in one sample period */
280 sw_counter_data[MMU_PAGE_FAULT_0 + event_id] += value;
281}
282
283GATOR_DEFINE_PROBE(mali_mmu_as_in_use, TP_PROTO(int event_id))
284{
285 record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_START);
286}
287
288GATOR_DEFINE_PROBE(mali_mmu_as_released, TP_PROTO(int event_id))
289{
290 record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_STOP);
291}
292
293GATOR_DEFINE_PROBE(mali_total_alloc_pages_change, TP_PROTO(long long int event_id))
294{
295 accumulators_data[TOTAL_ALLOC_PAGES] = event_id;
296}
297
298static int create_files(struct super_block *sb, struct dentry *root)
299{
300 int event;
301 /*
302 * Create the filesystem for all events
303 */
304 int counter_index = 0;
305 const char* mali_name = gator_mali_get_mali_name();
306
307 for (event = FIRST_TIMELINE_EVENT; event < FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS; event++)
308 {
309 if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event]) != 0)
310 {
311 return -1;
312 }
313 counter_index++;
314 }
315 counter_index = 0;
316 for (event = FIRST_SOFTWARE_COUNTER; event < FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS; event++)
317 {
318 if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event]) != 0)
319 {
320 return -1;
321 }
322 counter_index++;
323 }
324 counter_index = 0;
325 for (event = FIRST_ACCUMULATOR; event < FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS; event++)
326 {
327 if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event]) != 0)
328 {
329 return -1;
330 }
331 counter_index++;
332 }
333
334 return 0;
335}
336
337static int register_tracepoints(void)
338{
339 if (GATOR_REGISTER_TRACE(mali_pm_status))
340 {
341 pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint failed to activate\n");
342 return 0;
343 }
344
345 if (GATOR_REGISTER_TRACE(mali_page_fault_insert_pages))
346 {
347 pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint failed to activate\n");
348 return 0;
349 }
350
351 if (GATOR_REGISTER_TRACE(mali_mmu_as_in_use))
352 {
353 pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint failed to activate\n");
354 return 0;
355 }
356
357 if (GATOR_REGISTER_TRACE(mali_mmu_as_released))
358 {
359 pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint failed to activate\n");
360 return 0;
361 }
362
363 if (GATOR_REGISTER_TRACE(mali_total_alloc_pages_change))
364 {
365 pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint failed to activate\n");
366 return 0;
367 }
368
369 pr_debug("gator: Mali-T6xx: start\n");
370 pr_debug("gator: Mali-T6xx: mali_pm_status probe is at %p\n", &probe_mali_pm_status);
371 pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages probe is at %p\n", &probe_mali_page_fault_insert_pages);
372 pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use probe is at %p\n", &probe_mali_mmu_as_in_use);
373 pr_debug("gator: Mali-T6xx: mali_mmu_as_released probe is at %p\n", &probe_mali_mmu_as_released);
374 pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change probe is at %p\n", &probe_mali_total_alloc_pages_change);
375
376 return 1;
377}
378
379static int start(void)
380{
381 unsigned int cnt;
382
383 /* Clean all data for the next capture */
384 for (cnt = 0; cnt < NUMBER_OF_TIMELINE_EVENTS; cnt++)
385 {
386 timeline_event_starttime[cnt].tv_sec = timeline_event_starttime[cnt].tv_nsec = 0;
387 timeline_data[cnt] = 0;
388 }
389
390 for (cnt = 0; cnt < NUMBER_OF_SOFTWARE_COUNTERS; cnt++)
391 {
392 sw_counter_data[cnt] = 0;
393 }
394
395 for (cnt = 0; cnt < NUMBER_OF_ACCUMULATORS; cnt++)
396 {
397 accumulators_data[cnt] = 0;
398 }
399
400 /* Register tracepoints */
401 if (register_tracepoints() == 0)
402 {
403 return -1;
404 }
405
406 /*
407 * Set the first timestamp for calculating the sample interval. The first interval could be quite long,
408 * since it will be the time between 'start' and the first 'read'.
409 * This means that timeline values will be divided by a big number for the first sample.
410 */
411 getnstimeofday(&prev_timestamp);
412
413 return 0;
414}
415
416static void stop(void)
417{
418 pr_debug("gator: Mali-T6xx: stop\n");
419
420 /*
421 * It is safe to unregister traces even if they were not successfully
422 * registered, so no need to check.
423 */
424 GATOR_UNREGISTER_TRACE(mali_pm_status);
425 pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint deactivated\n");
426
427 GATOR_UNREGISTER_TRACE(mali_page_fault_insert_pages);
428 pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint deactivated\n");
429
430 GATOR_UNREGISTER_TRACE(mali_mmu_as_in_use);
431 pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint deactivated\n");
432
433 GATOR_UNREGISTER_TRACE(mali_mmu_as_released);
434 pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint deactivated\n");
435
436 GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change);
437 pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint deactivated\n");
438}
439
440static int read(int **buffer)
441{
442 int cnt;
443 int len = 0;
444 long sample_interval_us = 0;
445 struct timespec read_timestamp;
446
447 if (smp_processor_id()!=0)
448 {
449 return 0;
450 }
451
452 /* Get the start of this sample period. */
453 getnstimeofday(&read_timestamp);
454
455 /*
456 * Calculate the sample interval if the previous sample time is valid.
457 * We use tv_sec since it will not be 0.
458 */
459 if(prev_timestamp.tv_sec != 0) {
460 sample_interval_us = get_duration_us(&prev_timestamp, &read_timestamp);
461 }
462
463 /* Structure copy. Update the previous timestamp. */
464 prev_timestamp = read_timestamp;
465
466 /*
467 * Report the timeline counters (ACTIVITY_START/STOP)
468 */
469 for (cnt = FIRST_TIMELINE_EVENT; cnt < (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS); cnt++)
470 {
471 mali_counter *counter = &counters[cnt];
472 if (counter->enabled)
473 {
474 const int index = cnt - FIRST_TIMELINE_EVENT;
475 unsigned int value;
476
477 /* If the activity is still running, reset its start time to the start of this sample period
478 * to correct the count. Add the time up to the end of the sample onto the count. */
479 if(timeline_event_starttime[index].tv_sec != 0) {
480 const long event_duration = get_duration_us(&timeline_event_starttime[index], &read_timestamp);
481 timeline_data[index] += event_duration;
482 timeline_event_starttime[index] = read_timestamp; /* Activity is still running. */
483 }
484
485 if(sample_interval_us != 0) {
486 /* Convert the counter to a percent-of-sample value */
487 value = (timeline_data[index] * 100) / sample_interval_us;
488 } else {
489 pr_debug("gator: Mali-T6xx: setting value to zero\n");
490 value = 0;
491 }
492
493 /* Clear the counter value ready for the next sample. */
494 timeline_data[index] = 0;
495
496 counter_dump[len++] = counter->key;
497 counter_dump[len++] = value;
498 }
499 }
500
501 /* Report the software counters */
502 for (cnt = FIRST_SOFTWARE_COUNTER; cnt < (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS); cnt++)
503 {
504 const mali_counter *counter = &counters[cnt];
505 if (counter->enabled)
506 {
507 const int index = cnt - FIRST_SOFTWARE_COUNTER;
508 counter_dump[len++] = counter->key;
509 counter_dump[len++] = sw_counter_data[index];
510 /* Set the value to zero for the next time */
511 sw_counter_data[index] = 0;
512 }
513 }
514
515 /* Report the accumulators */
516 for (cnt = FIRST_ACCUMULATOR; cnt < (FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS); cnt++)
517 {
518 const mali_counter *counter = &counters[cnt];
519 if (counter->enabled)
520 {
521 const int index = cnt - FIRST_ACCUMULATOR;
522 counter_dump[len++] = counter->key;
523 counter_dump[len++] = accumulators_data[index];
524 /* Do not zero the accumulator */
525 }
526 }
527
528 /* Update the buffer */
529 if (buffer)
530 {
531 *buffer = (int*) counter_dump;
532 }
533
534 return len;
535}
536
537static struct gator_interface gator_events_mali_t6xx_interface = {
538 .create_files = create_files,
539 .start = start,
540 .stop = stop,
541 .read = read
542};
543
544extern int gator_events_mali_t6xx_init(void)
545{
546 pr_debug("gator: Mali-T6xx: sw_counters init\n");
547
548 gator_mali_initialise_counters(counters, NUMBER_OF_EVENTS);
549
550 return gator_events_install(&gator_events_mali_t6xx_interface);
551}
552
553gator_events_init(gator_events_mali_t6xx_init);
diff --git a/driver/gator_events_mali_t6xx_hw.c b/driver/gator_events_mali_t6xx_hw.c
new file mode 100644
index 0000000..12ffebc
--- /dev/null
+++ b/driver/gator_events_mali_t6xx_hw.c
@@ -0,0 +1,571 @@
1/*
2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2011-2012 ARM Limited
5 * ALL RIGHTS RESERVED
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
9 */
10
11#include "gator.h"
12
13#include <linux/module.h>
14#include <linux/time.h>
15#include <linux/math64.h>
16#include <linux/slab.h>
17#include <asm/io.h>
18
19/* Mali T6xx DDK includes */
20#include "linux/mali_linux_trace.h"
21#include "kbase/src/common/mali_kbase.h"
22#include "kbase/src/linux/mali_kbase_mem_linux.h"
23
24#include "gator_events_mali_common.h"
25
26/* Blocks for HW counters */
27enum
28{
29 JM_BLOCK = 0,
30 TILER_BLOCK,
31 SHADER_BLOCK,
32 MMU_BLOCK
33};
34
35/* Counters for Mali-T6xx:
36 *
37 * - HW counters, 4 blocks
38 * For HW counters we need strings to create /dev/gator/events files.
39 * Enums are not needed because the position of the HW name in the array is the same
40 * of the corresponding value in the received block of memory.
41 * HW counters are requested by calculating a bitmask, passed then to the driver.
42 * Every millisecond a HW counters dump is requested, and if the previous has been completed they are read.
43 */
44
45/* Hardware Counters */
46static const char* const hardware_counter_names [] =
47{
48 /* Job Manager */
49 "",
50 "",
51 "",
52 "",
53 "MESSAGES_SENT",
54 "MESSAGES_RECEIVED",
55 "GPU_ACTIVE", /* 6 */
56 "IRQ_ACTIVE",
57 "JS0_JOBS",
58 "JS0_TASKS",
59 "JS0_ACTIVE",
60 "",
61 "JS0_WAIT_READ",
62 "JS0_WAIT_ISSUE",
63 "JS0_WAIT_DEPEND",
64 "JS0_WAIT_FINISH",
65 "JS1_JOBS",
66 "JS1_TASKS",
67 "JS1_ACTIVE",
68 "",
69 "JS1_WAIT_READ",
70 "JS1_WAIT_ISSUE",
71 "JS1_WAIT_DEPEND",
72 "JS1_WAIT_FINISH",
73 "JS2_JOBS",
74 "JS2_TASKS",
75 "JS2_ACTIVE",
76 "",
77 "JS2_WAIT_READ",
78 "JS2_WAIT_ISSUE",
79 "JS2_WAIT_DEPEND",
80 "JS2_WAIT_FINISH",
81 "JS3_JOBS",
82 "JS3_TASKS",
83 "JS3_ACTIVE",
84 "",
85 "JS3_WAIT_READ",
86 "JS3_WAIT_ISSUE",
87 "JS3_WAIT_DEPEND",
88 "JS3_WAIT_FINISH",
89 "JS4_JOBS",
90 "JS4_TASKS",
91 "JS4_ACTIVE",
92 "",
93 "JS4_WAIT_READ",
94 "JS4_WAIT_ISSUE",
95 "JS4_WAIT_DEPEND",
96 "JS4_WAIT_FINISH",
97 "JS5_JOBS",
98 "JS5_TASKS",
99 "JS5_ACTIVE",
100 "",
101 "JS5_WAIT_READ",
102 "JS5_WAIT_ISSUE",
103 "JS5_WAIT_DEPEND",
104 "JS5_WAIT_FINISH",
105 "JS6_JOBS",
106 "JS6_TASKS",
107 "JS6_ACTIVE",
108 "",
109 "JS6_WAIT_READ",
110 "JS6_WAIT_ISSUE",
111 "JS6_WAIT_DEPEND",
112 "JS6_WAIT_FINISH",
113
114 /*Tiler*/
115 "",
116 "",
117 "",
118 "JOBS_PROCESSED",
119 "TRIANGLES",
120 "QUADS",
121 "POLYGONS",
122 "POINTS",
123 "LINES",
124 "VCACHE_HIT",
125 "VCACHE_MISS",
126 "FRONT_FACING",
127 "BACK_FACING",
128 "PRIM_VISIBLE",
129 "PRIM_CULLED",
130 "PRIM_CLIPPED",
131 "LEVEL0",
132 "LEVEL1",
133 "LEVEL2",
134 "LEVEL3",
135 "LEVEL4",
136 "LEVEL5",
137 "LEVEL6",
138 "LEVEL7",
139 "COMMAND_1",
140 "COMMAND_2",
141 "COMMAND_3",
142 "COMMAND_4",
143 "COMMAND_4_7",
144 "COMMAND_8_15",
145 "COMMAND_16_63",
146 "COMMAND_64",
147 "COMPRESS_IN",
148 "COMPRESS_OUT",
149 "COMPRESS_FLUSH",
150 "TIMESTAMPS",
151 "PCACHE_HIT",
152 "PCACHE_MISS",
153 "PCACHE_LINE",
154 "PCACHE_STALL",
155 "WRBUF_HIT",
156 "WRBUF_MISS",
157 "WRBUF_LINE",
158 "WRBUF_PARTIAL",
159 "WRBUF_STALL",
160 "ACTIVE",
161 "LOADING_DESC",
162 "INDEX_WAIT",
163 "INDEX_RANGE_WAIT",
164 "VERTEX_WAIT",
165 "PCACHE_WAIT",
166 "WRBUF_WAIT",
167 "BUS_READ",
168 "BUS_WRITE",
169 "",
170 "",
171 "",
172 "",
173 "",
174 "UTLB_STALL",
175 "UTLB_REPLAY_MISS",
176 "UTLB_REPLAY_FULL",
177 "UTLB_NEW_MISS",
178 "UTLB_HIT",
179
180 /* Shader Core */
181 "",
182 "",
183 "",
184 "SHADER_CORE_ACTIVE",
185 "FRAG_ACTIVE",
186 "FRAG_PRIMATIVES",
187 "FRAG_PRIMATIVES_DROPPED",
188 "FRAG_CYCLE_DESC",
189 "FRAG_CYCLES_PLR",
190 "FRAG_CYCLES_VERT",
191 "FRAG_CYCLES_TRISETUP",
192 "FRAG_CYCLES_RAST",
193 "FRAG_THREADS",
194 "FRAG_DUMMY_THREADS",
195 "FRAG_QUADS_RAST",
196 "FRAG_QUADS_EZS_TEST",
197 "FRAG_QUADS_EZS_KILLED",
198 "FRAG_QUADS_LZS_TEST",
199 "FRAG_QUADS_LZS_KILLED",
200 "FRAG_CYCLE_NO_TILE",
201 "FRAG_NUM_TILES",
202 "FRAG_TRANS_ELIM",
203 "COMPUTE_ACTIVE",
204 "COMPUTE_TASKS",
205 "COMPUTE_THREADS",
206 "COMPUTE_CYCLES_DESC",
207 "TRIPIPE_ACTIVE",
208 "ARITH_WORDS",
209 "ARITH_CYCLES_REG",
210 "ARITH_CYCLES_L0",
211 "ARITH_FRAG_DEPEND",
212 "LS_WORDS",
213 "LS_ISSUES",
214 "LS_RESTARTS",
215 "LS_REISSUES_MISS",
216 "LS_REISSUES_VD",
217 "LS_REISSUE_ATTRIB_MISS",
218 "LS_NO_WB",
219 "TEX_WORDS",
220 "TEX_BUBBLES",
221 "TEX_WORDS_L0",
222 "TEX_WORDS_DESC",
223 "TEX_THREADS",
224 "TEX_RECIRC_FMISS",
225 "TEX_RECIRC_DESC",
226 "TEX_RECIRC_MULTI",
227 "TEX_RECIRC_PMISS",
228 "TEX_RECIRC_CONF",
229 "LSC_READ_HITS",
230 "LSC_READ_MISSES",
231 "LSC_WRITE_HITS",
232 "LSC_WRITE_MISSES",
233 "LSC_ATOMIC_HITS",
234 "LSC_ATOMIC_MISSES",
235 "LSC_LINE_FETCHES",
236 "LSC_DIRTY_LINE",
237 "LSC_SNOOPS",
238 "AXI_TLB_STALL",
239 "AXI_TLB_MIESS",
240 "AXI_TLB_TRANSACTION",
241 "LS_TLB_MISS",
242 "LS_TLB_HIT",
243 "AXI_BEATS_READ",
244 "AXI_BEATS_WRITTEN",
245
246 /*L2 and MMU */
247 "",
248 "",
249 "",
250 "",
251 "MMU_TABLE_WALK",
252 "MMU_REPLAY_MISS",
253 "MMU_REPLAY_FULL",
254 "MMU_NEW_MISS",
255 "MMU_HIT",
256 "",
257 "",
258 "",
259 "",
260 "",
261 "",
262 "",
263 "UTLB_STALL",
264 "UTLB_REPLAY_MISS",
265 "UTLB_REPLAY_FULL",
266 "UTLB_NEW_MISS",
267 "UTLB_HIT",
268 "",
269 "",
270 "",
271 "",
272 "",
273 "",
274 "",
275 "",
276 "",
277 "L2_WRITE_BEATS",
278 "L2_READ_BEATS",
279 "L2_ANY_LOOKUP",
280 "L2_READ_LOOKUP",
281 "L2_SREAD_LOOKUP",
282 "L2_READ_REPLAY",
283 "L2_READ_SNOOP",
284 "L2_READ_HIT",
285 "L2_CLEAN_MISS",
286 "L2_WRITE_LOOKUP",
287 "L2_SWRITE_LOOKUP",
288 "L2_WRITE_REPLAY",
289 "L2_WRITE_SNOOP",
290 "L2_WRITE_HIT",
291 "L2_EXT_READ_FULL",
292 "L2_EXT_READ_HALF",
293 "L2_EXT_WRITE_FULL",
294 "L2_EXT_WRITE_HALF",
295 "L2_EXT_READ",
296 "L2_EXT_READ_LINE",
297 "L2_EXT_WRITE",
298 "L2_EXT_WRITE_LINE",
299 "L2_EXT_WRITE_SMALL",
300 "L2_EXT_BARRIER",
301 "L2_EXT_AR_STALL",
302 "L2_EXT_R_BUF_FULL",
303 "L2_EXT_RD_BUF_FULL",
304 "L2_EXT_R_RAW",
305 "L2_EXT_W_STALL",
306 "L2_EXT_W_BUF_FULL",
307 "L2_EXT_R_W_HAZARD",
308 "L2_TAG_HAZARD",
309 "L2_SNOOP_FULL",
310 "L2_REPLAY_FULL"
311};
312
313#define NUMBER_OF_HARDWARE_COUNTERS (sizeof(hardware_counter_names) / sizeof(hardware_counter_names[0]))
314
315#define GET_HW_BLOCK(c) (((c) >> 6) & 0x3)
316#define GET_COUNTER_OFFSET(c) ((c) & 0x3f)
317
318/* Memory to dump hardware counters into */
319static void *kernel_dump_buffer;
320
321/* kbase context and device */
322static kbase_context *kbcontext = NULL;
323static struct kbase_device *kbdevice = NULL;
324
325extern struct kbase_device *kbase_find_device(int minor);
326static volatile bool kbase_device_busy = false;
327static unsigned int num_hardware_counters_enabled;
328
329/*
330 * gatorfs variables for counter enable state
331 */
332static mali_counter counters[NUMBER_OF_HARDWARE_COUNTERS];
333
334/* An array used to return the data we recorded
335 * as key,value pairs hence the *2
336 */
337static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2];
338
339static int start(void)
340{
341 kbase_uk_hwcnt_setup setup;
342 mali_error err;
343 int cnt;
344 u16 bitmask[] = {0, 0, 0, 0};
345
346 /* Setup HW counters */
347 num_hardware_counters_enabled = 0;
348
349 if(NUMBER_OF_HARDWARE_COUNTERS != 256)
350 {
351 pr_debug("Unexpected number of hardware counters defined: expecting 256, got %d\n", NUMBER_OF_HARDWARE_COUNTERS);
352 }
353
354 /* Calculate enable bitmasks based on counters_enabled array */
355 for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++)
356 {
357 const mali_counter *counter = &counters[cnt];
358 if (counter->enabled)
359 {
360 int block = GET_HW_BLOCK(cnt);
361 int enable_bit = GET_COUNTER_OFFSET(cnt) / 4;
362 bitmask[block] |= (1 << enable_bit);
363 pr_debug("gator: Mali-T6xx: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt);
364 num_hardware_counters_enabled++;
365 }
366 }
367
368 /* Create a kbase context for HW counters */
369 if (num_hardware_counters_enabled > 0)
370 {
371 kbdevice = kbase_find_device(-1);
372
373 if (kbcontext)
374 return -1;
375
376 kbcontext = kbase_create_context(kbdevice);
377 if (!kbcontext)
378 {
379 pr_debug("gator: Mali-T6xx: error creating kbase context\n");
380 goto out;
381 }
382
383 /*
384 * The amount of memory needed to store the dump (bytes)
385 * DUMP_SIZE = number of core groups
386 * * number of blocks (always 8 for midgard)
387 * * number of counters per block (always 64 for midgard)
388 * * number of bytes per counter (always 4 in midgard)
389 * For a Mali-T6xx with a single core group = 1 * 8 * 64 * 4
390 */
391 kernel_dump_buffer = kbase_va_alloc(kbcontext, 2048);
392 if (!kernel_dump_buffer)
393 {
394 pr_debug("gator: Mali-T6xx: error trying to allocate va\n");
395 goto destroy_context;
396 }
397
398 setup.dump_buffer = (uintptr_t)kernel_dump_buffer;
399 setup.jm_bm = bitmask[JM_BLOCK];
400 setup.tiler_bm = bitmask[TILER_BLOCK];
401 setup.shader_bm = bitmask[SHADER_BLOCK];
402 setup.mmu_l2_bm = bitmask[MMU_BLOCK];
403 /* These counters do not exist on Mali-T60x */
404 setup.l3_cache_bm = 0;
405
406 /* Use kbase API to enable hardware counters and provide dump buffer */
407 err = kbase_instr_hwcnt_enable(kbcontext, &setup);
408 if (err != MALI_ERROR_NONE)
409 {
410 pr_debug("gator: Mali-T6xx: can't setup hardware counters\n");
411 goto free_buffer;
412 }
413 pr_debug("gator: Mali-T6xx: hardware counters enabled\n");
414 kbase_instr_hwcnt_clear(kbcontext);
415 pr_debug("gator: Mali-T6xx: hardware counters cleared \n");
416
417 kbase_device_busy = false;
418 }
419
420 return 0;
421
422 free_buffer:
423 kbase_va_free(kbcontext, kernel_dump_buffer);
424 destroy_context:
425 kbase_destroy_context(kbcontext);
426 out:
427 return -1;
428}
429
430static void stop(void) {
431 unsigned int cnt;
432 kbase_context *temp_kbcontext;
433
434 pr_debug("gator: Mali-T6xx: stop\n");
435
436 /* Set all counters as disabled */
437 for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) {
438 counters[cnt].enabled = 0;
439 }
440
441 /* Destroy the context for HW counters */
442 if (num_hardware_counters_enabled > 0 && kbcontext != NULL)
443 {
444 /*
445 * Set the global variable to NULL before destroying it, because
446 * other function will check this before using it.
447 */
448 temp_kbcontext = kbcontext;
449 kbcontext = NULL;
450
451 kbase_instr_hwcnt_disable(temp_kbcontext);
452 kbase_va_free(temp_kbcontext, kernel_dump_buffer);
453 kbase_destroy_context(temp_kbcontext);
454 pr_debug("gator: Mali-T6xx: hardware counters stopped\n");
455 }
456}
457
458static int read(int **buffer) {
459 int cnt;
460 int len = 0;
461 u32 value = 0;
462 mali_bool success;
463
464 if (smp_processor_id()!=0)
465 {
466 return 0;
467 }
468
469 /*
470 * Report the HW counters
471 * Only process hardware counters if at least one of the hardware counters is enabled.
472 */
473 if (num_hardware_counters_enabled > 0)
474 {
475 const unsigned int vithar_blocks[] = {
476 0x700, /* VITHAR_JOB_MANAGER, Block 0 */
477 0x400, /* VITHAR_TILER, Block 1 */
478 0x000, /* VITHAR_SHADER_CORE, Block 2 */
479 0x500 /* VITHAR_MEMORY_SYSTEM, Block 3 */
480 };
481
482 if (!kbcontext)
483 {
484 return -1;
485 }
486
487 // TODO: SYMBOL_GET (all kbase functions)
488 if (kbase_instr_hwcnt_dump_complete(kbcontext, &success) == MALI_TRUE)
489 {
490 kbase_device_busy = false;
491
492 if (success == MALI_TRUE)
493 {
494 for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++)
495 {
496 const mali_counter *counter = &counters[cnt];
497 if (counter->enabled)
498 {
499 const int block = GET_HW_BLOCK(cnt);
500 const int counter_offset = GET_COUNTER_OFFSET(cnt);
501 const u32 *counter_block = (u32 *)((uintptr_t)kernel_dump_buffer + vithar_blocks[block]);
502 const u32 *counter_address = counter_block + counter_offset;
503
504 value = *counter_address;
505
506 if(block == SHADER_BLOCK){
507 /* (counter_address + 0x000) has already been accounted-for above. */
508 value += *(counter_address + 0x100);
509 value += *(counter_address + 0x200);
510 value += *(counter_address + 0x300);
511 }
512
513 counter_dump[len++] = counter->key;
514 counter_dump[len++] = value;
515 }
516 }
517 }
518 }
519
520 if (! kbase_device_busy)
521 {
522 kbase_device_busy = true;
523 kbase_instr_hwcnt_dump_irq(kbcontext);
524 }
525 }
526
527 /* Update the buffer */
528 if (buffer) {
529 *buffer = (int*) counter_dump;
530 }
531
532 return len;
533}
534
535static int create_files(struct super_block *sb, struct dentry *root)
536{
537 unsigned int event;
538 /*
539 * Create the filesystem for all events
540 */
541 int counter_index = 0;
542 const char* mali_name = gator_mali_get_mali_name();
543
544 for (event = 0; event < NUMBER_OF_HARDWARE_COUNTERS; event++)
545 {
546 if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event]) != 0)
547 return -1;
548 counter_index++;
549 }
550
551 return 0;
552}
553
554
555static struct gator_interface gator_events_mali_t6xx_interface = {
556 .create_files = create_files,
557 .start = start,
558 .stop = stop,
559 .read = read
560};
561
562int gator_events_mali_t6xx_hw_init(void)
563{
564 pr_debug("gator: Mali-T6xx: sw_counters init\n");
565
566 gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS);
567
568 return gator_events_install(&gator_events_mali_t6xx_interface);
569}
570
571gator_events_init(gator_events_mali_t6xx_hw_init);
diff --git a/driver/gator_events_meminfo.c b/driver/gator_events_meminfo.c
index f9dfa9a..b962641 100644
--- a/driver/gator_events_meminfo.c
+++ b/driver/gator_events_meminfo.c
@@ -26,7 +26,6 @@ static unsigned int mem_event = 0;
26static bool new_data_avail; 26static bool new_data_avail;
27 27
28static void wq_sched_handler(struct work_struct *wsptr); 28static void wq_sched_handler(struct work_struct *wsptr);
29
30DECLARE_WORK(work, wq_sched_handler); 29DECLARE_WORK(work, wq_sched_handler);
31static struct timer_list meminfo_wake_up_timer; 30static struct timer_list meminfo_wake_up_timer;
32static void meminfo_wake_up_handler(unsigned long unused_data); 31static void meminfo_wake_up_handler(unsigned long unused_data);
@@ -141,9 +140,9 @@ static void gator_events_meminfo_stop(void)
141 GATOR_UNREGISTER_TRACE(mm_page_free_batched); 140 GATOR_UNREGISTER_TRACE(mm_page_free_batched);
142#endif 141#endif
143 GATOR_UNREGISTER_TRACE(mm_page_alloc); 142 GATOR_UNREGISTER_TRACE(mm_page_alloc);
144 }
145 143
146 del_timer_sync(&meminfo_wake_up_timer); 144 del_timer_sync(&meminfo_wake_up_timer);
145 }
147 146
148 meminfo_global_enabled = 0; 147 meminfo_global_enabled = 0;
149 for (i = 0; i < MEMINFO_TOTAL; i++) { 148 for (i = 0; i < MEMINFO_TOTAL; i++) {
diff --git a/driver/gator_events_net.c b/driver/gator_events_net.c
index a3ae3f0..11282b5 100644
--- a/driver/gator_events_net.c
+++ b/driver/gator_events_net.c
@@ -25,6 +25,7 @@ static int netGet[TOTALNET * 4];
25 25
26static struct timer_list net_wake_up_timer; 26static struct timer_list net_wake_up_timer;
27 27
28// Must be run in process context as the kernel function dev_get_stats() can sleep
28static void get_network_stats(struct work_struct *wsptr) { 29static void get_network_stats(struct work_struct *wsptr) {
29 int rx = 0, tx = 0; 30 int rx = 0, tx = 0;
30 struct net_device *dev; 31 struct net_device *dev;
diff --git a/driver/gator_events_perf_pmu.c b/driver/gator_events_perf_pmu.c
index da76a9c..9d78b46 100755..100644
--- a/driver/gator_events_perf_pmu.c
+++ b/driver/gator_events_perf_pmu.c
@@ -32,6 +32,7 @@ static DEFINE_PER_CPU(int[CNTMAX], perfPrevDelta);
32static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt); 32static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt);
33static DEFINE_PER_CPU(struct perf_event *[CNTMAX], pevent); 33static DEFINE_PER_CPU(struct perf_event *[CNTMAX], pevent);
34static DEFINE_PER_CPU(struct perf_event_attr *[CNTMAX], pevent_attr); 34static DEFINE_PER_CPU(struct perf_event_attr *[CNTMAX], pevent_attr);
35extern DEFINE_PER_CPU(struct perf_event *, pevent_ebs);
35 36
36static void gator_events_perf_pmu_stop(void); 37static void gator_events_perf_pmu_stop(void);
37 38
@@ -74,10 +75,15 @@ static void dummy_handler(struct perf_event *event, struct perf_sample_data *dat
74static int gator_events_perf_pmu_online(int** buffer) 75static int gator_events_perf_pmu_online(int** buffer)
75{ 76{
76 int cnt, len = 0, cpu = smp_processor_id(); 77 int cnt, len = 0, cpu = smp_processor_id();
78 struct perf_event * ev;
77 79
78 // read the counters and toss the invalid data, return zero instead 80 // read the counters and toss the invalid data, return zero instead
79 for (cnt = 0; cnt < pmnc_counters; cnt++) { 81 for (cnt = 0; cnt < pmnc_counters; cnt++) {
80 struct perf_event * ev = per_cpu(pevent, cpu)[cnt]; 82 if (pmnc_count[cnt] > 0) {
83 ev = per_cpu(pevent_ebs, cpu); // special case for EBS
84 } else {
85 ev = per_cpu(pevent, cpu)[cnt];
86 }
81 if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) { 87 if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
82 ev->pmu->read(ev); 88 ev->pmu->read(ev);
83 per_cpu(perfPrev, cpu)[cnt] = per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count); 89 per_cpu(perfPrev, cpu)[cnt] = per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count);
@@ -101,6 +107,9 @@ static void gator_events_perf_pmu_online_dispatch(int cpu)
101 if (per_cpu(pevent, cpu)[cnt] != NULL || per_cpu(pevent_attr, cpu)[cnt] == 0) 107 if (per_cpu(pevent, cpu)[cnt] != NULL || per_cpu(pevent_attr, cpu)[cnt] == 0)
102 continue; 108 continue;
103 109
110 if (pmnc_count[cnt] > 0)
111 continue; // skip the EBS counter
112
104#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) 113#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
105 per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, dummy_handler); 114 per_cpu(pevent, cpu)[cnt] = perf_event_create_kernel_counter(per_cpu(pevent_attr, cpu)[cnt], cpu, 0, dummy_handler);
106#else 115#else
@@ -203,14 +212,19 @@ static int gator_events_perf_pmu_read(int **buffer)
203{ 212{
204 int cnt, delta, len = 0; 213 int cnt, delta, len = 0;
205 int cpu = smp_processor_id(); 214 int cpu = smp_processor_id();
215 struct perf_event * ev;
206 216
207 for (cnt = 0; cnt < pmnc_counters; cnt++) { 217 for (cnt = 0; cnt < pmnc_counters; cnt++) {
208 struct perf_event * ev = per_cpu(pevent, cpu)[cnt]; 218 if (pmnc_count[cnt] > 0) {
219 ev = per_cpu(pevent_ebs, cpu); // special case for EBS
220 } else {
221 ev = per_cpu(pevent, cpu)[cnt];
222 }
209 if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) { 223 if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
210 ev->pmu->read(ev); 224 ev->pmu->read(ev);
211 per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count); 225 per_cpu(perfCurr, cpu)[cnt] = local64_read(&ev->count);
212 delta = per_cpu(perfCurr, cpu)[cnt] - per_cpu(perfPrev, cpu)[cnt]; 226 delta = per_cpu(perfCurr, cpu)[cnt] - per_cpu(perfPrev, cpu)[cnt];
213 if (delta != per_cpu(perfPrevDelta, cpu)[cnt]) { 227 if (delta != 0 || delta != per_cpu(perfPrevDelta, cpu)[cnt]) {
214 per_cpu(perfPrevDelta, cpu)[cnt] = delta; 228 per_cpu(perfPrevDelta, cpu)[cnt] = delta;
215 per_cpu(perfPrev, cpu)[cnt] = per_cpu(perfCurr, cpu)[cnt]; 229 per_cpu(perfPrev, cpu)[cnt] = per_cpu(perfCurr, cpu)[cnt];
216 per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt]; 230 per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt];
diff --git a/driver/gator_fs.c b/driver/gator_fs.c
index 39adfbe..81b0d5b 100644
--- a/driver/gator_fs.c
+++ b/driver/gator_fs.c
@@ -251,7 +251,6 @@ static int gatorfs_fill_super(struct super_block *sb, void *data, int silent)
251 251
252 gator_op_create_files(sb, root_dentry); 252 gator_op_create_files(sb, root_dentry);
253 253
254 // FIXME: verify kill_litter_super removes our dentries
255 return 0; 254 return 0;
256} 255}
257 256
diff --git a/driver/gator_hrtimer_gator.c b/driver/gator_hrtimer_gator.c
index 846fba4..846fba4 100755..100644
--- a/driver/gator_hrtimer_gator.c
+++ b/driver/gator_hrtimer_gator.c
diff --git a/driver/gator_main.c b/driver/gator_main.c
index 994e35d..db728ad 100644
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
@@ -7,7 +7,7 @@
7 * 7 *
8 */ 8 */
9 9
10static unsigned long gator_protocol_version = 9; 10static unsigned long gator_protocol_version = 10;
11 11
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/cpu.h> 13#include <linux/cpu.h>
@@ -48,9 +48,9 @@ static unsigned long gator_protocol_version = 9;
48 48
49#if (GATOR_PERF_SUPPORT) && (!(GATOR_PERF_PMU_SUPPORT)) 49#if (GATOR_PERF_SUPPORT) && (!(GATOR_PERF_PMU_SUPPORT))
50#ifndef CONFIG_PERF_EVENTS 50#ifndef CONFIG_PERF_EVENTS
51#warning gator requires the kernel to have CONFIG_PERF_EVENTS defined to support pmu hardware counters 51#error gator requires the kernel to have CONFIG_PERF_EVENTS defined to support pmu hardware counters
52#elif !defined CONFIG_HW_PERF_EVENTS 52#elif !defined CONFIG_HW_PERF_EVENTS
53#warning gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters 53#error gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters
54#endif 54#endif
55#endif 55#endif
56 56
@@ -108,6 +108,9 @@ static DEFINE_MUTEX(start_mutex);
108static DEFINE_MUTEX(gator_buffer_mutex); 108static DEFINE_MUTEX(gator_buffer_mutex);
109 109
110bool event_based_sampling; 110bool event_based_sampling;
111#if defined(__arm__) && (GATOR_PERF_PMU_SUPPORT)
112DEFINE_PER_CPU(struct perf_event *, pevent_ebs);
113#endif
111 114
112static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait); 115static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
113static struct timer_list gator_buffer_wake_up_timer; 116static struct timer_list gator_buffer_wake_up_timer;
@@ -690,11 +693,6 @@ static void gator_stop(void)
690{ 693{
691 struct gator_interface *gi; 694 struct gator_interface *gi;
692 695
693 // stop all events
694 list_for_each_entry(gi, &gator_events, list)
695 if (gi->stop)
696 gi->stop();
697
698 gator_annotate_stop(); 696 gator_annotate_stop();
699 gator_trace_sched_stop(); 697 gator_trace_sched_stop();
700 gator_trace_power_stop(); 698 gator_trace_power_stop();
@@ -704,6 +702,11 @@ static void gator_stop(void)
704 // stop all interrupt callback reads before tearing down other interfaces 702 // stop all interrupt callback reads before tearing down other interfaces
705 gator_notifier_stop(); // should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined 703 gator_notifier_stop(); // should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined
706 gator_timer_stop(); 704 gator_timer_stop();
705
706 // stop all events
707 list_for_each_entry(gi, &gator_events, list)
708 if (gi->stop)
709 gi->stop();
707} 710}
708 711
709/****************************************************************************** 712/******************************************************************************
diff --git a/driver/gator_marshaling.c b/driver/gator_marshaling.c
index 630d142..630d142 100755..100644
--- a/driver/gator_marshaling.c
+++ b/driver/gator_marshaling.c
diff --git a/driver/gator_trace_gpu.c b/driver/gator_trace_gpu.c
index 921932c..d053987 100644
--- a/driver/gator_trace_gpu.c
+++ b/driver/gator_trace_gpu.c
@@ -18,11 +18,19 @@
18#endif 18#endif
19#include "gator_trace_gpu.h" 19#include "gator_trace_gpu.h"
20 20
21#define ACTIVITY_START 1 21/*
22#define ACTIVITY_STOP 2 22 * Taken from MALI_PROFILING_EVENT_TYPE_* items in Mali DDK.
23 */
24#define EVENT_TYPE_SINGLE 0
25#define EVENT_TYPE_START 1
26#define EVENT_TYPE_STOP 2
27#define EVENT_TYPE_SUSPEND 3
28#define EVENT_TYPE_RESUME 4
29
23 30
24/* Note whether tracepoints have been registered */ 31/* Note whether tracepoints have been registered */
25static int mali_trace_registered; 32static int mali_timeline_trace_registered;
33static int mali_job_slots_trace_registered;
26static int gpu_trace_registered; 34static int gpu_trace_registered;
27 35
28#define GPU_START 1 36#define GPU_START 1
@@ -32,42 +40,107 @@ static int gpu_trace_registered;
32#define GPU_UNIT_FP 2 40#define GPU_UNIT_FP 2
33#define GPU_UNIT_CL 3 41#define GPU_UNIT_CL 3
34 42
35#ifdef MALI_SUPPORT 43#define MALI_400 (0x0b07)
44#define MALI_T6xx (0x0056)
45
46#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
47#include "gator_events_mali_400.h"
36 48
37enum components { 49/*
38 COMPONENT_VP0 = 1, 50 * Taken from MALI_PROFILING_EVENT_CHANNEL_* in Mali DDK.
39 COMPONENT_FP0 = 5, 51 */
40 COMPONENT_FP1, 52enum {
41 COMPONENT_FP2, 53 EVENT_CHANNEL_SOFTWARE = 0,
42 COMPONENT_FP3, 54 EVENT_CHANNEL_VP0 = 1,
43 COMPONENT_FP4, 55 EVENT_CHANNEL_FP0 = 5,
44 COMPONENT_FP5, 56 EVENT_CHANNEL_FP1,
45 COMPONENT_FP6, 57 EVENT_CHANNEL_FP2,
46 COMPONENT_FP7, 58 EVENT_CHANNEL_FP3,
59 EVENT_CHANNEL_FP4,
60 EVENT_CHANNEL_FP5,
61 EVENT_CHANNEL_FP6,
62 EVENT_CHANNEL_FP7,
63 EVENT_CHANNEL_GPU = 21
64};
65
66/**
67 * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from the GPU channel
68 */
69enum {
70 EVENT_REASON_SINGLE_GPU_NONE = 0,
71 EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1,
47}; 72};
48 73
74
49GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned int d2, unsigned int d3, unsigned int d4)) 75GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned int d2, unsigned int d3, unsigned int d4))
50{ 76{
51 unsigned int component, state; 77 unsigned int component, state;
52 int tgid = 0, pid = 0;
53 78
54 // do as much work as possible before disabling interrupts 79 // do as much work as possible before disabling interrupts
55 component = (event_id >> 16) & 0xFF; // component is an 8-bit field 80 component = (event_id >> 16) & 0xFF; // component is an 8-bit field
56 state = (event_id >> 24) & 0xF; // state is a 4-bit field 81 state = (event_id >> 24) & 0xF; // state is a 4-bit field
57 82
58 if ((component == COMPONENT_VP0) || (component >= COMPONENT_FP0 && component <= COMPONENT_FP7)) { 83 switch (state) {
59 if (state == ACTIVITY_START || state == ACTIVITY_STOP) { 84 case EVENT_TYPE_START:
60 unsigned int type = (state == ACTIVITY_START) ? GPU_START : GPU_STOP; 85 if (component == EVENT_CHANNEL_VP0) {
61 unsigned int unit = (component < COMPONENT_FP0) ? GPU_UNIT_VP : GPU_UNIT_FP; 86 /* tgid = d0; pid = d1; */
62 unsigned int core = (component < COMPONENT_FP0) ? component - COMPONENT_VP0 : component - COMPONENT_FP0; 87 marshal_sched_gpu(GPU_START, GPU_UNIT_VP, 0, d0, d1);
63 if (state == ACTIVITY_START) { 88 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
64 tgid = d0; 89 /* tgid = d0; pid = d1; */
65 pid = d1; 90 marshal_sched_gpu(GPU_START, GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, d0, d1);
91 }
92 break;
93
94 case EVENT_TYPE_STOP:
95 if (component == EVENT_CHANNEL_VP0) {
96 marshal_sched_gpu(GPU_STOP, GPU_UNIT_VP, 0, 0, 0);
97 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
98 marshal_sched_gpu(GPU_STOP, GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, 0, 0);
99 }
100 break;
101
102 case EVENT_TYPE_SINGLE:
103 if (component == EVENT_CHANNEL_GPU) {
104 unsigned int reason = (event_id & 0xffff);
105
106 if(reason == EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE) {
107 gator_events_mali_log_dvfs_event(d0, d1);
66 } 108 }
109 }
110 break;
67 111
68 marshal_sched_gpu(type, unit, core, tgid, pid); 112 default:
69 } 113 break;
70 } 114 }
115}
116#endif
117
118#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
119GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid))
120{
121 unsigned int component, state, type, unit = 0;
122
123 component = (event_id >> 16) & 0xFF; // component is an 8-bit field
124 state = (event_id >> 24) & 0xF; // state is a 4-bit field
125 type = (state == EVENT_TYPE_START) ? GPU_START : GPU_STOP;
126
127 switch (component)
128 {
129 case 0:
130 unit = GPU_UNIT_FP;
131 break;
132 case 1:
133 unit = GPU_UNIT_VP;
134 break;
135 case 2:
136 unit = GPU_UNIT_CL;
137 break;
138 }
139
140 if (unit != 0)
141 {
142 marshal_sched_gpu(type, unit, 0, tgid, (pid != 0 ? pid : tgid));
143 }
71} 144}
72#endif 145#endif
73 146
@@ -88,15 +161,21 @@ int gator_trace_gpu_start(void)
88 * Absence of gpu trace points is not an error 161 * Absence of gpu trace points is not an error
89 */ 162 */
90 163
91 gpu_trace_registered = mali_trace_registered = 0; 164 gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
92 165
93#ifdef MALI_SUPPORT 166#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
94 if (!GATOR_REGISTER_TRACE(mali_timeline_event)) { 167 if (!GATOR_REGISTER_TRACE(mali_timeline_event)) {
95 mali_trace_registered = 1; 168 mali_timeline_trace_registered = 1;
96 } 169 }
97#endif 170#endif
98 171
99 if (!mali_trace_registered) { 172#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
173 if (!GATOR_REGISTER_TRACE(mali_job_slots_event)) {
174 mali_job_slots_trace_registered = 1;
175 }
176#endif
177
178 if (!mali_timeline_trace_registered) {
100 if (GATOR_REGISTER_TRACE(gpu_activity_start)) { 179 if (GATOR_REGISTER_TRACE(gpu_activity_start)) {
101 return 0; 180 return 0;
102 } 181 }
@@ -112,15 +191,22 @@ int gator_trace_gpu_start(void)
112 191
113void gator_trace_gpu_stop(void) 192void gator_trace_gpu_stop(void)
114{ 193{
115#ifdef MALI_SUPPORT 194#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
116 if (mali_trace_registered) { 195 if (mali_timeline_trace_registered) {
117 GATOR_UNREGISTER_TRACE(mali_timeline_event); 196 GATOR_UNREGISTER_TRACE(mali_timeline_event);
118 } 197 }
119#endif 198#endif
199
200#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
201 if (mali_job_slots_trace_registered) {
202 GATOR_UNREGISTER_TRACE(mali_job_slots_event);
203 }
204#endif
205
120 if (gpu_trace_registered) { 206 if (gpu_trace_registered) {
121 GATOR_UNREGISTER_TRACE(gpu_activity_stop); 207 GATOR_UNREGISTER_TRACE(gpu_activity_stop);
122 GATOR_UNREGISTER_TRACE(gpu_activity_start); 208 GATOR_UNREGISTER_TRACE(gpu_activity_start);
123 } 209 }
124 210
125 gpu_trace_registered = mali_trace_registered = 0; 211 gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
126} 212}
diff --git a/driver/gator_trace_power.c b/driver/gator_trace_power.c
index ca89b19..ca89b19 100755..100644
--- a/driver/gator_trace_power.c
+++ b/driver/gator_trace_power.c
diff --git a/driver/mali_t6xx.mk b/driver/mali_t6xx.mk
new file mode 100644
index 0000000..2e51670
--- /dev/null
+++ b/driver/mali_t6xx.mk
@@ -0,0 +1,24 @@
1# Defines for Mali-T6xx driver
2EXTRA_CFLAGS += -DMALI_USE_UMP=1 \
3 -DMALI_LICENSE_IS_GPL=1 \
4 -DMALI_BASE_TRACK_MEMLEAK=0 \
5 -DMALI_DEBUG=0 \
6 -DMALI_ERROR_INJECT_ON=0 \
7 -DMALI_CUSTOMER_RELEASE=1 \
8 -DMALI_UNIT_TEST=0 \
9 -DMALI_BACKEND_KERNEL=1 \
10 -DMALI_NO_MALI=0
11
12KBASE_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase
13OSK_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase/osk
14UMP_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/ump
15
16# Include directories in the DDK
17EXTRA_CFLAGS += -I$(DDK_DIR) \
18 -I$(KBASE_DIR)/.. \
19 -I$(OSK_DIR)/.. \
20 -I$(UMP_DIR)/.. \
21 -I$(KBASE_DIR)/osk/src/linux/include \
22 -I$(KBASE_DIR)/platform_dummy \
23 -I$(KBASE_DIR)/src
24