diff options
Diffstat (limited to 'driver')
-rw-r--r-- | driver/Makefile | 7 | ||||
-rw-r--r-- | driver/gator_annotate.c | 9 | ||||
-rw-r--r-- | driver/gator_cookies.c | 5 | ||||
-rw-r--r-- | driver/gator_ebs.c | 18 | ||||
-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.h | 19 | ||||
-rw-r--r-- | driver/gator_events_mali_common.c | 79 | ||||
-rw-r--r-- | driver/gator_events_mali_common.h | 85 | ||||
-rw-r--r-- | driver/gator_events_mali_t6xx.c | 553 | ||||
-rw-r--r-- | driver/gator_events_mali_t6xx_hw.c | 571 | ||||
-rw-r--r-- | driver/gator_events_meminfo.c | 5 | ||||
-rw-r--r-- | driver/gator_events_net.c | 1 | ||||
-rw-r--r--[-rwxr-xr-x] | driver/gator_events_perf_pmu.c | 20 | ||||
-rw-r--r-- | driver/gator_fs.c | 1 | ||||
-rw-r--r--[-rwxr-xr-x] | driver/gator_hrtimer_gator.c | 0 | ||||
-rw-r--r-- | driver/gator_main.c | 19 | ||||
-rw-r--r--[-rwxr-xr-x] | driver/gator_marshaling.c | 0 | ||||
-rw-r--r-- | driver/gator_trace_gpu.c | 152 | ||||
-rw-r--r--[-rwxr-xr-x] | driver/gator_trace_power.c | 0 | ||||
-rw-r--r-- | driver/mali_t6xx.mk | 24 |
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 | ||
18 | ifneq ($(GATOR_WITH_MALI_SUPPORT),) | 18 | ifneq ($(GATOR_WITH_MALI_SUPPORT),) |
19 | ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_T6xx) | 19 | ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_T6xx) |
20 | gator-y += gator_events_mali_t6xx.o | 20 | gator-y += gator_events_mali_t6xx.o \ |
21 | gator_events_mali_t6xx_hw.o | ||
22 | include $(M)/mali_t6xx.mk | ||
21 | else | 23 | else |
22 | gator-y += gator_events_mali.o | 24 | gator-y += gator_events_mali_400.o |
23 | endif | 25 | endif |
26 | gator-y += gator_events_mali_common.o | ||
24 | EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT) | 27 | EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT) |
25 | endif | 28 | endif |
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); | |||
27 | DECLARE_WORK(cookie_work, wq_cookie_handler); | 27 | DECLARE_WORK(cookie_work, wq_cookie_handler); |
28 | static struct timer_list app_process_wake_up_timer; | 28 | static struct timer_list app_process_wake_up_timer; |
29 | static void app_process_wake_up_handler(unsigned long unused_data); | 29 | static void app_process_wake_up_handler(unsigned long unused_data); |
30 | static struct timer_list app_process_wake_up_timer; | ||
31 | static void app_process_wake_up_handler(unsigned long unused_data); | ||
32 | 30 | ||
33 | static uint32_t cookiemap_code(uint64_t value64) { | 31 | static 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 | ||
387 | cookie_setup_error: | 386 | cookie_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[]; | |||
23 | extern unsigned long pmnc_count[]; | 23 | extern unsigned long pmnc_count[]; |
24 | extern unsigned long pmnc_key[]; | 24 | extern unsigned long pmnc_key[]; |
25 | 25 | ||
26 | static DEFINE_PER_CPU(struct perf_event *, pevent); | ||
27 | static DEFINE_PER_CPU(struct perf_event_attr *, pevent_attr); | 26 | static DEFINE_PER_CPU(struct perf_event_attr *, pevent_attr); |
28 | static DEFINE_PER_CPU(int, key); | 27 | static DEFINE_PER_CPU(int, key); |
29 | static 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) |
32 | static void ebs_overflow_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs) | 30 | static 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 | ||
77 | static void gator_event_sampling_offline_dispatch(int cpu) | 75 | static 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 | ||
61 | static 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 | ||
63 | enum counters { | 54 | enum 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 | */ |
177 | static u32 get_difference(u32 start, u32 end) | 170 | static 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 |
272 | GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void * surface_id, unsigned int * counters)) | 269 | GATOR_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. */ |
288 | u32 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]); |
293 | u32 gator_mali_get_id(void) { | 279 | } |
294 | return MALI_SUPPORT; | 280 | } |
295 | } | 281 | } |
282 | #endif /* GATOR_MALI_INTERFACE_STYLE == 3 */ | ||
296 | 283 | ||
297 | int gator_events_mali_create_files(struct super_block *sb, struct dentry *root) { | 284 | static 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 | /* |
415 | void _mali_profiling_set_event(unsigned int, unsigned int); | 418 | * Local store for the get_counters entry point into the DDK. |
416 | void _mali_osk_fb_control_set(unsigned int, unsigned int); | 419 | * This is stored here since it is used very regularly. |
417 | void _mali_profiling_control(unsigned int, unsigned int); | 420 | */ |
418 | 421 | static mali_profiling_get_counters_type *mali_get_counters = NULL; | |
419 | void _mali_profiling_get_counters(unsigned int*, unsigned int*, unsigned int*, unsigned int*); | ||
420 | void (*_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 | */ |
426 | static int is_any_sw_counter_enabled(void) | 427 | static 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 | ||
441 | static void mali_counter_initialize(void) | 442 | static 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 | ||
515 | static void mali_counter_deinitialize(void) | 516 | static 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 | ||
570 | static int gator_events_mali_start(void) { | 571 | static 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 | ||
601 | static void gator_events_mali_stop(void) { | 602 | static 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 | ||
635 | static int gator_events_mali_read(int **buffer) { | 636 | static 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 | ||
688 | static struct gator_interface gator_events_mali_interface = { | 706 | static 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 | ||
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 | } | ||
717 | |||
695 | int gator_events_mali_init(void) | 718 | int 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 | |||
732 | gator_events_init(gator_events_mali_init); | 737 | gator_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 | |||
17 | extern 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 | |||
12 | static u32 gator_mali_get_id(void) | ||
13 | { | ||
14 | return MALI_SUPPORT; | ||
15 | } | ||
16 | |||
17 | extern 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 | |||
32 | extern 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 | |||
69 | extern 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 | */ | ||
37 | typedef 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 | |||
42 | typedef void mali_profiling_set_event_type(unsigned int, unsigned int); | ||
43 | typedef void mali_osk_fb_control_set_type(unsigned int, unsigned int); | ||
44 | typedef void mali_profiling_control_type(unsigned int, unsigned int); | ||
45 | typedef 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 | */ | ||
50 | extern void _mali_profiling_set_event(unsigned int, unsigned int); | ||
51 | extern void _mali_osk_fb_control_set(unsigned int, unsigned int); | ||
52 | extern void _mali_profiling_control(unsigned int, unsigned int); | ||
53 | extern 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 | */ | ||
60 | extern 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 | */ | ||
75 | extern 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 | */ | ||
83 | extern 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 */ | ||
47 | static 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 | |||
66 | enum | ||
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 */ | ||
88 | static 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 | |||
96 | enum | ||
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 */ | ||
105 | static const char* accumulators_names [] = | ||
106 | { | ||
107 | "TOTAL_ALLOC_PAGES" | ||
108 | }; | ||
109 | |||
110 | enum | ||
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 | */ | ||
126 | static 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 | */ | ||
131 | static 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 | */ | ||
137 | static struct timespec timeline_event_starttime[NUMBER_OF_TIMELINE_EVENTS]; | ||
138 | |||
139 | /* The data we have recorded */ | ||
140 | static unsigned int timeline_data[NUMBER_OF_TIMELINE_EVENTS]; | ||
141 | static unsigned int sw_counter_data[NUMBER_OF_SOFTWARE_COUNTERS]; | ||
142 | static unsigned int accumulators_data[NUMBER_OF_ACCUMULATORS]; | ||
143 | |||
144 | /* Hold the previous timestamp, used to calculate the sample interval. */ | ||
145 | static 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 | */ | ||
155 | static 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 | |||
163 | static 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 | |||
206 | GATOR_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 | |||
277 | GATOR_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 | |||
283 | GATOR_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 | |||
288 | GATOR_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 | |||
293 | GATOR_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 | |||
298 | static 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 | |||
337 | static 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 | |||
379 | static 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 | |||
416 | static 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 | |||
440 | static 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 | |||
537 | static struct gator_interface gator_events_mali_t6xx_interface = { | ||
538 | .create_files = create_files, | ||
539 | .start = start, | ||
540 | .stop = stop, | ||
541 | .read = read | ||
542 | }; | ||
543 | |||
544 | extern 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 | |||
553 | gator_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 */ | ||
27 | enum | ||
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 */ | ||
46 | static 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 */ | ||
319 | static void *kernel_dump_buffer; | ||
320 | |||
321 | /* kbase context and device */ | ||
322 | static kbase_context *kbcontext = NULL; | ||
323 | static struct kbase_device *kbdevice = NULL; | ||
324 | |||
325 | extern struct kbase_device *kbase_find_device(int minor); | ||
326 | static volatile bool kbase_device_busy = false; | ||
327 | static unsigned int num_hardware_counters_enabled; | ||
328 | |||
329 | /* | ||
330 | * gatorfs variables for counter enable state | ||
331 | */ | ||
332 | static 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 | */ | ||
337 | static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2]; | ||
338 | |||
339 | static 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 | |||
430 | static 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 | |||
458 | static 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 | |||
535 | static 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 | |||
555 | static struct gator_interface gator_events_mali_t6xx_interface = { | ||
556 | .create_files = create_files, | ||
557 | .start = start, | ||
558 | .stop = stop, | ||
559 | .read = read | ||
560 | }; | ||
561 | |||
562 | int 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 | |||
571 | gator_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; | |||
26 | static bool new_data_avail; | 26 | static bool new_data_avail; |
27 | 27 | ||
28 | static void wq_sched_handler(struct work_struct *wsptr); | 28 | static void wq_sched_handler(struct work_struct *wsptr); |
29 | |||
30 | DECLARE_WORK(work, wq_sched_handler); | 29 | DECLARE_WORK(work, wq_sched_handler); |
31 | static struct timer_list meminfo_wake_up_timer; | 30 | static struct timer_list meminfo_wake_up_timer; |
32 | static void meminfo_wake_up_handler(unsigned long unused_data); | 31 | static 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 | ||
26 | static struct timer_list net_wake_up_timer; | 26 | static 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 | ||
28 | static void get_network_stats(struct work_struct *wsptr) { | 29 | static 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); | |||
32 | static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt); | 32 | static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt); |
33 | static DEFINE_PER_CPU(struct perf_event *[CNTMAX], pevent); | 33 | static DEFINE_PER_CPU(struct perf_event *[CNTMAX], pevent); |
34 | static DEFINE_PER_CPU(struct perf_event_attr *[CNTMAX], pevent_attr); | 34 | static DEFINE_PER_CPU(struct perf_event_attr *[CNTMAX], pevent_attr); |
35 | extern DEFINE_PER_CPU(struct perf_event *, pevent_ebs); | ||
35 | 36 | ||
36 | static void gator_events_perf_pmu_stop(void); | 37 | static 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 | |||
74 | static int gator_events_perf_pmu_online(int** buffer) | 75 | static 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 | ||
10 | static unsigned long gator_protocol_version = 9; | 10 | static 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); | |||
108 | static DEFINE_MUTEX(gator_buffer_mutex); | 108 | static DEFINE_MUTEX(gator_buffer_mutex); |
109 | 109 | ||
110 | bool event_based_sampling; | 110 | bool event_based_sampling; |
111 | #if defined(__arm__) && (GATOR_PERF_PMU_SUPPORT) | ||
112 | DEFINE_PER_CPU(struct perf_event *, pevent_ebs); | ||
113 | #endif | ||
111 | 114 | ||
112 | static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait); | 115 | static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait); |
113 | static struct timer_list gator_buffer_wake_up_timer; | 116 | static 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 */ |
25 | static int mali_trace_registered; | 32 | static int mali_timeline_trace_registered; |
33 | static int mali_job_slots_trace_registered; | ||
26 | static int gpu_trace_registered; | 34 | static 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 | ||
37 | enum components { | 49 | /* |
38 | COMPONENT_VP0 = 1, | 50 | * Taken from MALI_PROFILING_EVENT_CHANNEL_* in Mali DDK. |
39 | COMPONENT_FP0 = 5, | 51 | */ |
40 | COMPONENT_FP1, | 52 | enum { |
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 | */ | ||
69 | enum { | ||
70 | EVENT_REASON_SINGLE_GPU_NONE = 0, | ||
71 | EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1, | ||
47 | }; | 72 | }; |
48 | 73 | ||
74 | |||
49 | GATOR_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)) | 75 | GATOR_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) | ||
119 | GATOR_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 | ||
113 | void gator_trace_gpu_stop(void) | 192 | void 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 | ||
2 | EXTRA_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 | |||
12 | KBASE_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase | ||
13 | OSK_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/t6xx/kbase/osk | ||
14 | UMP_DIR = $(DDK_DIR)/kernel/drivers/gpu/arm/ump | ||
15 | |||
16 | # Include directories in the DDK | ||
17 | EXTRA_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 | |||