blob: 6332098e595840d9ffe1797b22addf39d006fa60 [file] [log] [blame]
Jon Medhurstaaf37a32013-06-11 12:10:56 +01001/**
Jon Medhurst15ce78d2014-04-10 09:02:02 +01002 * Copyright (C) ARM Limited 2010-2014. All rights reserved.
Jon Medhurstaaf37a32013-06-11 12:10:56 +01003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include "gator.h"
10
11#include <linux/slab.h>
12#include <linux/module.h>
13#include <linux/time.h>
14#include <linux/math64.h>
15
16#ifdef MALI_SUPPORT
Jon Medhurst15ce78d2014-04-10 09:02:02 +010017#ifdef MALI_DIR_MIDGARD
18/* New DDK Directory structure with kernel/drivers/gpu/arm/midgard*/
19#include "mali_linux_trace.h"
20#else
21/* Old DDK Directory structure with kernel/drivers/gpu/arm/t6xx*/
Jon Medhurstaaf37a32013-06-11 12:10:56 +010022#include "linux/mali_linux_trace.h"
23#endif
Jon Medhurst15ce78d2014-04-10 09:02:02 +010024#endif
25
Jon Medhurstaaf37a32013-06-11 12:10:56 +010026#include "gator_trace_gpu.h"
27
28/*
29 * Taken from MALI_PROFILING_EVENT_TYPE_* items in Mali DDK.
30 */
31#define EVENT_TYPE_SINGLE 0
32#define EVENT_TYPE_START 1
33#define EVENT_TYPE_STOP 2
34#define EVENT_TYPE_SUSPEND 3
35#define EVENT_TYPE_RESUME 4
36
37/* Note whether tracepoints have been registered */
38static int mali_timeline_trace_registered;
39static int mali_job_slots_trace_registered;
40static int gpu_trace_registered;
41
42enum {
43 GPU_UNIT_NONE = 0,
44 GPU_UNIT_VP,
45 GPU_UNIT_FP,
46 GPU_UNIT_CL,
47 NUMBER_OF_GPU_UNITS
48};
49
Jon Medhurstd3698592013-10-10 16:48:56 +010050#define MALI_4xx (0x0b07)
Jon Medhurstaaf37a32013-06-11 12:10:56 +010051#define MALI_T6xx (0x0056)
52
53struct mali_gpu_job {
54 int count;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010055 int last_tgid;
56 int last_pid;
Jon Medhurstd3698592013-10-10 16:48:56 +010057 int last_job_id;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010058};
59
60#define NUMBER_OF_GPU_CORES 16
61static struct mali_gpu_job mali_gpu_jobs[NUMBER_OF_GPU_UNITS][NUMBER_OF_GPU_CORES];
62static DEFINE_SPINLOCK(mali_gpu_jobs_lock);
63
Jon Medhurstd3698592013-10-10 16:48:56 +010064/* Only one event should be running on a unit and core at a time (ie, a start
65 * event can only be followed by a stop and vice versa), but because the kernel
66 * only knows when a job is enqueued and not started, it is possible for a
67 * start1, start2, stop1, stop2. Change it back into start1, stop1, start2,
68 * stop2 by queueing up start2 and releasing it when stop1 is received.
69 */
70static void mali_gpu_enqueue(int unit, int core, int tgid, int pid, int job_id)
Jon Medhurstaaf37a32013-06-11 12:10:56 +010071{
72 int count;
73
74 spin_lock(&mali_gpu_jobs_lock);
75 count = mali_gpu_jobs[unit][core].count;
76 BUG_ON(count < 0);
77 ++mali_gpu_jobs[unit][core].count;
78 if (count) {
Jon Medhurstaaf37a32013-06-11 12:10:56 +010079 mali_gpu_jobs[unit][core].last_tgid = tgid;
80 mali_gpu_jobs[unit][core].last_pid = pid;
Jon Medhurstd3698592013-10-10 16:48:56 +010081 mali_gpu_jobs[unit][core].last_job_id = job_id;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010082 }
83 spin_unlock(&mali_gpu_jobs_lock);
84
85 if (!count) {
Jon Medhurstd3698592013-10-10 16:48:56 +010086 marshal_sched_gpu_start(unit, core, tgid, pid/*, job_id*/);
Jon Medhurstaaf37a32013-06-11 12:10:56 +010087 }
88}
89
90static void mali_gpu_stop(int unit, int core)
91{
92 int count;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010093 int last_tgid = 0;
94 int last_pid = 0;
Jon Medhurst34d97692013-12-19 09:23:06 +000095 //int last_job_id = 0;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010096
97 spin_lock(&mali_gpu_jobs_lock);
98 if (mali_gpu_jobs[unit][core].count == 0) {
99 spin_unlock(&mali_gpu_jobs_lock);
100 return;
101 }
102 --mali_gpu_jobs[unit][core].count;
103 count = mali_gpu_jobs[unit][core].count;
104 if (count) {
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100105 last_tgid = mali_gpu_jobs[unit][core].last_tgid;
106 last_pid = mali_gpu_jobs[unit][core].last_pid;
Jon Medhurst34d97692013-12-19 09:23:06 +0000107 //last_job_id = mali_gpu_jobs[unit][core].last_job_id;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100108 }
109 spin_unlock(&mali_gpu_jobs_lock);
110
111 marshal_sched_gpu_stop(unit, core);
112 if (count) {
Jon Medhurstd3698592013-10-10 16:48:56 +0100113 marshal_sched_gpu_start(unit, core, last_tgid, last_pid/*, last_job_id*/);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100114 }
115}
116
117#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
Jon Medhurstd3698592013-10-10 16:48:56 +0100118#include "gator_events_mali_4xx.h"
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100119
120/*
121 * Taken from MALI_PROFILING_EVENT_CHANNEL_* in Mali DDK.
122 */
123enum {
124 EVENT_CHANNEL_SOFTWARE = 0,
125 EVENT_CHANNEL_VP0 = 1,
126 EVENT_CHANNEL_FP0 = 5,
127 EVENT_CHANNEL_FP1,
128 EVENT_CHANNEL_FP2,
129 EVENT_CHANNEL_FP3,
130 EVENT_CHANNEL_FP4,
131 EVENT_CHANNEL_FP5,
132 EVENT_CHANNEL_FP6,
133 EVENT_CHANNEL_FP7,
134 EVENT_CHANNEL_GPU = 21
135};
136
137/**
138 * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from the GPU channel
139 */
140enum {
141 EVENT_REASON_SINGLE_GPU_NONE = 0,
142 EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1,
143};
144
145GATOR_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))
146{
147 unsigned int component, state;
148
149 // do as much work as possible before disabling interrupts
150 component = (event_id >> 16) & 0xFF; // component is an 8-bit field
151 state = (event_id >> 24) & 0xF; // state is a 4-bit field
152
153 switch (state) {
154 case EVENT_TYPE_START:
155 if (component == EVENT_CHANNEL_VP0) {
156 /* tgid = d0; pid = d1; */
Jon Medhurstd3698592013-10-10 16:48:56 +0100157 mali_gpu_enqueue(GPU_UNIT_VP, 0, d0, d1, 0);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100158 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
159 /* tgid = d0; pid = d1; */
Jon Medhurstd3698592013-10-10 16:48:56 +0100160 mali_gpu_enqueue(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0, d0, d1, 0);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100161 }
162 break;
163
164 case EVENT_TYPE_STOP:
165 if (component == EVENT_CHANNEL_VP0) {
166 mali_gpu_stop(GPU_UNIT_VP, 0);
167 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
168 mali_gpu_stop(GPU_UNIT_FP, component - EVENT_CHANNEL_FP0);
169 }
170 break;
171
172 case EVENT_TYPE_SINGLE:
173 if (component == EVENT_CHANNEL_GPU) {
174 unsigned int reason = (event_id & 0xffff);
175
176 if (reason == EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE) {
177 gator_events_mali_log_dvfs_event(d0, d1);
178 }
179 }
180 break;
181
182 default:
183 break;
184 }
185}
186#endif
187
188#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
Jon Medhurstd3698592013-10-10 16:48:56 +0100189#if defined(MALI_JOB_SLOTS_EVENT_CHANGED)
190GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid, unsigned char job_id))
191#else
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100192GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid))
Jon Medhurstd3698592013-10-10 16:48:56 +0100193#endif
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100194{
195 unsigned int component, state, unit;
Jon Medhurstd3698592013-10-10 16:48:56 +0100196#if !defined(MALI_JOB_SLOTS_EVENT_CHANGED)
197 unsigned char job_id = 0;
198#endif
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100199
200 component = (event_id >> 16) & 0xFF; // component is an 8-bit field
201 state = (event_id >> 24) & 0xF; // state is a 4-bit field
202
203 switch (component) {
204 case 0:
205 unit = GPU_UNIT_FP;
206 break;
207 case 1:
208 unit = GPU_UNIT_VP;
209 break;
210 case 2:
211 unit = GPU_UNIT_CL;
212 break;
213 default:
214 unit = GPU_UNIT_NONE;
215 }
216
217 if (unit != GPU_UNIT_NONE) {
218 switch (state) {
219 case EVENT_TYPE_START:
Jon Medhurstd3698592013-10-10 16:48:56 +0100220 mali_gpu_enqueue(unit, 0, tgid, (pid != 0 ? pid : tgid), job_id);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100221 break;
222 case EVENT_TYPE_STOP:
223 mali_gpu_stop(unit, 0);
224 break;
225 default:
226 /*
227 * Some jobs can be soft-stopped, so ensure that this terminates the activity trace.
228 */
229 mali_gpu_stop(unit, 0);
230 }
231 }
232}
233#endif
234
235GATOR_DEFINE_PROBE(gpu_activity_start, TP_PROTO(int gpu_unit, int gpu_core, struct task_struct *p))
236{
Jon Medhurstd3698592013-10-10 16:48:56 +0100237 mali_gpu_enqueue(gpu_unit, gpu_core, (int)p->tgid, (int)p->pid, 0);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100238}
239
240GATOR_DEFINE_PROBE(gpu_activity_stop, TP_PROTO(int gpu_unit, int gpu_core))
241{
242 mali_gpu_stop(gpu_unit, gpu_core);
243}
244
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100245static int gator_trace_gpu_start(void)
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100246{
247 /*
248 * Returns nonzero for installation failed
249 * Absence of gpu trace points is not an error
250 */
251
Jon Medhurst34d97692013-12-19 09:23:06 +0000252 memset(&mali_gpu_jobs, 0, sizeof(mali_gpu_jobs));
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100253 gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
254
255#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
256 if (!GATOR_REGISTER_TRACE(mali_timeline_event)) {
257 mali_timeline_trace_registered = 1;
258 }
259#endif
260
261#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
262 if (!GATOR_REGISTER_TRACE(mali_job_slots_event)) {
263 mali_job_slots_trace_registered = 1;
264 }
265#endif
266
267 if (!mali_timeline_trace_registered) {
268 if (GATOR_REGISTER_TRACE(gpu_activity_start)) {
269 return 0;
270 }
271 if (GATOR_REGISTER_TRACE(gpu_activity_stop)) {
272 GATOR_UNREGISTER_TRACE(gpu_activity_start);
273 return 0;
274 }
275 gpu_trace_registered = 1;
276 }
277
278 return 0;
279}
280
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100281static void gator_trace_gpu_stop(void)
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100282{
283#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx)
284 if (mali_timeline_trace_registered) {
285 GATOR_UNREGISTER_TRACE(mali_timeline_event);
286 }
287#endif
288
289#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx)
290 if (mali_job_slots_trace_registered) {
291 GATOR_UNREGISTER_TRACE(mali_job_slots_event);
292 }
293#endif
294
295 if (gpu_trace_registered) {
296 GATOR_UNREGISTER_TRACE(gpu_activity_stop);
297 GATOR_UNREGISTER_TRACE(gpu_activity_start);
298 }
299
300 gpu_trace_registered = mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
301}