2 * Copyright (C) ARM Limited 2010-2013. 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 #include "linux/mali_linux_trace.h"
19 #include "gator_trace_gpu.h"
22 * Taken from MALI_PROFILING_EVENT_TYPE_* items in Mali DDK.
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
30 /* Note whether tracepoints have been registered */
31 static int mali_timeline_trace_registered;
32 static int mali_job_slots_trace_registered;
33 static int gpu_trace_registered;
43 #define MALI_4xx (0x0b07)
44 #define MALI_T6xx (0x0056)
53 #define NUMBER_OF_GPU_CORES 16
54 static struct mali_gpu_job mali_gpu_jobs[NUMBER_OF_GPU_UNITS][NUMBER_OF_GPU_CORES];
55 static DEFINE_SPINLOCK(mali_gpu_jobs_lock);
57 /* Only one event should be running on a unit and core at a time (ie, a start
58 * event can only be followed by a stop and vice versa), but because the kernel
59 * only knows when a job is enqueued and not started, it is possible for a
60 * start1, start2, stop1, stop2. Change it back into start1, stop1, start2,
61 * stop2 by queueing up start2 and releasing it when stop1 is received.
63 static void mali_gpu_enqueue(int unit, int core, int tgid, int pid, int job_id)
67 spin_lock(&mali_gpu_jobs_lock);
68 count = mali_gpu_jobs[unit][core].count;
70 ++mali_gpu_jobs[unit][core].count;
72 mali_gpu_jobs[unit][core].last_tgid = tgid;
73 mali_gpu_jobs[unit][core].last_pid = pid;
74 mali_gpu_jobs[unit][core].last_job_id = job_id;
76 spin_unlock(&mali_gpu_jobs_lock);
79 marshal_sched_gpu_start(unit, core, tgid, pid/*, job_id*/);
83 static void mali_gpu_stop(int unit, int core)
90 spin_lock(&mali_gpu_jobs_lock);
91 if (mali_gpu_jobs[unit][core].count == 0) {
92 spin_unlock(&mali_gpu_jobs_lock);
95 --mali_gpu_jobs[unit][core].count;
96 count = mali_gpu_jobs[unit][core].count;
98 last_tgid = mali_gpu_jobs[unit][core].last_tgid;
99 last_pid = mali_gpu_jobs[unit][core].last_pid;
100 last_job_id = mali_gpu_jobs[unit][core].last_job_id;
102 spin_unlock(&mali_gpu_jobs_lock);
104 marshal_sched_gpu_stop(unit, core);
106 marshal_sched_gpu_start(unit, core, last_tgid, last_pid/*, last_job_id*/);
110 #if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
111 #include "gator_events_mali_4xx.h"
114 * Taken from MALI_PROFILING_EVENT_CHANNEL_* in Mali DDK.
117 EVENT_CHANNEL_SOFTWARE = 0,
118 EVENT_CHANNEL_VP0 = 1,
119 EVENT_CHANNEL_FP0 = 5,
127 EVENT_CHANNEL_GPU = 21
131 * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from the GPU channel
134 EVENT_REASON_SINGLE_GPU_NONE = 0,
135 EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1,
138 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))
140 unsigned int component, state;
142 // do as much work as possible before disabling interrupts
143 component = (event_id >> 16) & 0xFF; // component is an 8-bit field
144 state = (event_id >> 24) & 0xF; // state is a 4-bit field
147 case EVENT_TYPE_START:
148 if (component == EVENT_CHANNEL_VP0) {
149 /* tgid = d0; pid = d1; */
150 mali_gpu_enqueue(GPU_UNIT_VP, 0, d0, d1, 0);
151 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
152 /* tgid = d0; pid = d1; */
153 mali_gpu_enqueue(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, d0, d1, 0);
157 case EVENT_TYPE_STOP:
158 if (component == EVENT_CHANNEL_VP0) {
159 mali_gpu_stop(GPU_UNIT_VP, 0);
160 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
161 mali_gpu_stop(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0);
165 case EVENT_TYPE_SINGLE:
166 if (component == EVENT_CHANNEL_GPU) {
167 unsigned int reason = (event_id & 0xffff);
169 if (reason == EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE) {
170 gator_events_mali_log_dvfs_event(d0, d1);
181 #if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
182 #if defined(MALI_JOB_SLOTS_EVENT_CHANGED)
183 GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid, unsigned char job_id))
185 GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid))
188 unsigned int component, state, unit;
189 #if !defined(MALI_JOB_SLOTS_EVENT_CHANGED)
190 unsigned char job_id = 0;
193 component = (event_id >> 16) & 0xFF; // component is an 8-bit field
194 state = (event_id >> 24) & 0xF; // state is a 4-bit field
207 unit = GPU_UNIT_NONE;
210 if (unit != GPU_UNIT_NONE) {
212 case EVENT_TYPE_START:
213 mali_gpu_enqueue(unit, 0, tgid, (pid != 0 ? pid : tgid), job_id);
215 case EVENT_TYPE_STOP:
216 mali_gpu_stop(unit, 0);
220 * Some jobs can be soft-stopped, so ensure that this terminates the activity trace.
222 mali_gpu_stop(unit, 0);
228 GATOR_DEFINE_PROBE(gpu_activity_start, TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p))
230 mali_gpu_enqueue(gpu_unit, gpu_core, (int)p->tgid, (int)p->pid, 0);
233 GATOR_DEFINE_PROBE(gpu_activity_stop, TP_PROTO(int gpu_unit, int gpu_core))
235 mali_gpu_stop(gpu_unit, gpu_core);
238 int gator_trace_gpu_start(void)
241 * Returns nonzero for installation failed
242 * Absence of gpu trace points is not an error
245 memset(&mali_gpu_jobs, sizeof(mali_gpu_jobs), 0);
246 gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
248 #if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
249 if (!GATOR_REGISTER_TRACE(mali_timeline_event)) {
250 mali_timeline_trace_registered = 1;
254 #if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
255 if (!GATOR_REGISTER_TRACE(mali_job_slots_event)) {
256 mali_job_slots_trace_registered = 1;
260 if (!mali_timeline_trace_registered) {
261 if (GATOR_REGISTER_TRACE(gpu_activity_start)) {
264 if (GATOR_REGISTER_TRACE(gpu_activity_stop)) {
265 GATOR_UNREGISTER_TRACE(gpu_activity_start);
268 gpu_trace_registered = 1;
274 void gator_trace_gpu_stop(void)
276 #if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
277 if (mali_timeline_trace_registered) {
278 GATOR_UNREGISTER_TRACE(mali_timeline_event);
282 #if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
283 if (mali_job_slots_trace_registered) {
284 GATOR_UNREGISTER_TRACE(mali_job_slots_event);
288 if (gpu_trace_registered) {
289 GATOR_UNREGISTER_TRACE(gpu_activity_stop);
290 GATOR_UNREGISTER_TRACE(gpu_activity_start);
293 gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;