2 * Copyright (C) ARM Limited 2010-2014. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
11 #include <linux/slab.h>
12 #include <linux/module.h>
13 #include <linux/time.h>
14 #include <linux/math64.h>
17 #ifdef MALI_DIR_MIDGARD
18 /* New DDK Directory structure with kernel/drivers/gpu/arm/midgard*/
19 #include "mali_linux_trace.h"
21 /* Old DDK Directory structure with kernel/drivers/gpu/arm/t6xx*/
22 #include "linux/mali_linux_trace.h"
27 * Taken from MALI_PROFILING_EVENT_TYPE_* items in Mali DDK.
29 #define EVENT_TYPE_SINGLE 0
30 #define EVENT_TYPE_START 1
31 #define EVENT_TYPE_STOP 2
32 #define EVENT_TYPE_SUSPEND 3
33 #define EVENT_TYPE_RESUME 4
35 /* Note whether tracepoints have been registered */
36 static int mali_timeline_trace_registered;
37 static int mali_job_slots_trace_registered;
47 #if defined(MALI_SUPPORT)
49 struct mali_activity {
57 #define NUMBER_OF_GPU_CORES 16
58 static struct mali_activity mali_activities[NUMBER_OF_GPU_UNITS*NUMBER_OF_GPU_CORES];
59 static DEFINE_SPINLOCK(mali_activities_lock);
61 /* Only one event should be running on a unit and core at a time (ie,
62 * a start event can only be followed by a stop and vice versa), but
63 * because the kernel only knows when a job is enqueued and not
64 * started, it is possible for a start1, start2, stop1, stop2. Change
65 * it back into start1, stop1, start2, stop2 by queueing up start2 and
66 * releasing it when stop1 is received.
69 static int mali_activity_index(int core, int key)
73 for (i = 0; i < ARRAY_SIZE(mali_activities); ++i) {
74 if ((mali_activities[i].core == core) && (mali_activities[i].key == key))
76 if ((mali_activities[i].core == 0) && (mali_activities[i].key == 0)) {
77 mali_activities[i].core = core;
78 mali_activities[i].key = key;
82 BUG_ON(i >= ARRAY_SIZE(mali_activities));
87 static void mali_activity_enqueue(int core, int key, int activity, int pid)
92 spin_lock(&mali_activities_lock);
93 i = mali_activity_index(core, key);
95 count = mali_activities[i].count;
97 ++mali_activities[i].count;
99 mali_activities[i].last_activity = activity;
100 mali_activities[i].last_pid = pid;
102 spin_unlock(&mali_activities_lock);
105 gator_marshal_activity_switch(core, key, activity, pid);
108 static void mali_activity_stop(int core, int key)
112 int last_activity = 0;
115 spin_lock(&mali_activities_lock);
116 i = mali_activity_index(core, key);
118 if (mali_activities[i].count == 0) {
119 spin_unlock(&mali_activities_lock);
122 --mali_activities[i].count;
123 count = mali_activities[i].count;
125 last_activity = mali_activities[i].last_activity;
126 last_pid = mali_activities[i].last_pid;
128 spin_unlock(&mali_activities_lock);
130 gator_marshal_activity_switch(core, key, 0, 0);
132 gator_marshal_activity_switch(core, key, last_activity, last_pid);
135 void mali_activity_clear(struct mali_counter mali_activity[], size_t mali_activity_size)
141 for (activity = 0; activity < mali_activity_size; ++activity) {
142 cores = mali_activity[activity].cores;
145 for (core = 0; core < cores; ++core) {
146 if (mali_activity[activity].enabled) {
148 gator_marshal_activity_switch(core, mali_activity[activity].key, 0, 0);
157 #if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD)
158 #include "gator_events_mali_4xx.h"
161 * Taken from MALI_PROFILING_EVENT_CHANNEL_* in Mali DDK.
164 EVENT_CHANNEL_SOFTWARE = 0,
165 EVENT_CHANNEL_VP0 = 1,
166 EVENT_CHANNEL_FP0 = 5,
174 EVENT_CHANNEL_GPU = 21
178 * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from the GPU channel
181 EVENT_REASON_SINGLE_GPU_NONE = 0,
182 EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1,
185 struct mali_counter mali_activity[2];
187 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))
189 unsigned int component, state;
191 /* do as much work as possible before disabling interrupts */
192 component = (event_id >> 16) & 0xFF; /* component is an 8-bit field */
193 state = (event_id >> 24) & 0xF; /* state is a 4-bit field */
196 case EVENT_TYPE_START:
197 if (component == EVENT_CHANNEL_VP0) {
198 /* tgid = d0; pid = d1; */
199 if (mali_activity[1].enabled)
200 mali_activity_enqueue(0, mali_activity[1].key, 1, d1);
201 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
202 /* tgid = d0; pid = d1; */
203 if (mali_activity[0].enabled)
204 mali_activity_enqueue(component - EVENT_CHANNEL_FP0, mali_activity[0].key, 1, d1);
208 case EVENT_TYPE_STOP:
209 if (component == EVENT_CHANNEL_VP0) {
210 if (mali_activity[1].enabled)
211 mali_activity_stop(0, mali_activity[1].key);
212 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
213 if (mali_activity[0].enabled)
214 mali_activity_stop(component - EVENT_CHANNEL_FP0, mali_activity[0].key);
218 case EVENT_TYPE_SINGLE:
219 if (component == EVENT_CHANNEL_GPU) {
220 unsigned int reason = (event_id & 0xffff);
222 if (reason == EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE)
223 gator_events_mali_log_dvfs_event(d0, d1);
233 #if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD)
235 struct mali_counter mali_activity[3];
237 #if defined(MALI_JOB_SLOTS_EVENT_CHANGED)
238 GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid, unsigned char job_id))
240 GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid))
243 unsigned int component, state, unit;
244 #if !defined(MALI_JOB_SLOTS_EVENT_CHANGED)
245 unsigned char job_id = 0;
248 component = (event_id >> 16) & 0xFF; /* component is an 8-bit field */
249 state = (event_id >> 24) & 0xF; /* state is a 4-bit field */
262 unit = GPU_UNIT_NONE;
265 if (unit != GPU_UNIT_NONE) {
267 case EVENT_TYPE_START:
268 if (mali_activity[component].enabled)
269 mali_activity_enqueue(0, mali_activity[component].key, 1, (pid != 0 ? pid : tgid));
271 case EVENT_TYPE_STOP:
272 default: /* Some jobs can be soft-stopped, so ensure that this terminates the activity trace. */
273 if (mali_activity[component].enabled)
274 mali_activity_stop(0, mali_activity[component].key);
281 static int gator_trace_gpu_start(void)
284 * Returns nonzero for installation failed
285 * Absence of gpu trace points is not an error
288 #if defined(MALI_SUPPORT)
289 memset(&mali_activities, 0, sizeof(mali_activities));
291 mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
293 #if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD)
294 mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity));
295 if (!GATOR_REGISTER_TRACE(mali_timeline_event))
296 mali_timeline_trace_registered = 1;
299 #if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD)
300 mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity));
301 if (!GATOR_REGISTER_TRACE(mali_job_slots_event))
302 mali_job_slots_trace_registered = 1;
308 static void gator_trace_gpu_stop(void)
310 #if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD)
311 if (mali_timeline_trace_registered)
312 GATOR_UNREGISTER_TRACE(mali_timeline_event);
315 #if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD)
316 if (mali_job_slots_trace_registered)
317 GATOR_UNREGISTER_TRACE(mali_job_slots_event);
320 mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;