blob: d9b82ee1857f1900019925e2715a360c4355d5e1 [file] [log] [blame]
Jon Medhurstaaf37a32013-06-11 12:10:56 +01001/**
Jon Medhurstb1d07442015-05-08 12:04:18 +01002 * Copyright (C) ARM Limited 2010-2015. 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/*
27 * Taken from MALI_PROFILING_EVENT_TYPE_* items in Mali DDK.
28 */
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
34
35/* Note whether tracepoints have been registered */
36static int mali_timeline_trace_registered;
37static int mali_job_slots_trace_registered;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010038
39enum {
40 GPU_UNIT_NONE = 0,
41 GPU_UNIT_VP,
42 GPU_UNIT_FP,
43 GPU_UNIT_CL,
44 NUMBER_OF_GPU_UNITS
45};
46
Jon Medhurste31266f2014-08-04 15:47:44 +010047#if defined(MALI_SUPPORT)
Jon Medhurstaaf37a32013-06-11 12:10:56 +010048
Jon Medhurste31266f2014-08-04 15:47:44 +010049struct mali_activity {
50 int core;
51 int key;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010052 int count;
Jon Medhurste31266f2014-08-04 15:47:44 +010053 int last_activity;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010054 int last_pid;
55};
56
57#define NUMBER_OF_GPU_CORES 16
Jon Medhurste31266f2014-08-04 15:47:44 +010058static struct mali_activity mali_activities[NUMBER_OF_GPU_UNITS*NUMBER_OF_GPU_CORES];
59static DEFINE_SPINLOCK(mali_activities_lock);
Jon Medhurstaaf37a32013-06-11 12:10:56 +010060
Jon Medhurst96b56152014-10-30 18:01:15 +000061/* 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.
Jon Medhurstd3698592013-10-10 16:48:56 +010067 */
Jon Medhurste31266f2014-08-04 15:47:44 +010068
69static int mali_activity_index(int core, int key)
Jon Medhurstaaf37a32013-06-11 12:10:56 +010070{
Jon Medhurste31266f2014-08-04 15:47:44 +010071 int i;
72
73 for (i = 0; i < ARRAY_SIZE(mali_activities); ++i) {
Jon Medhurst96b56152014-10-30 18:01:15 +000074 if ((mali_activities[i].core == core) && (mali_activities[i].key == key))
Jon Medhurste31266f2014-08-04 15:47:44 +010075 break;
Jon Medhurste31266f2014-08-04 15:47:44 +010076 if ((mali_activities[i].core == 0) && (mali_activities[i].key == 0)) {
77 mali_activities[i].core = core;
78 mali_activities[i].key = key;
79 break;
80 }
81 }
82 BUG_ON(i >= ARRAY_SIZE(mali_activities));
83
84 return i;
85}
86
87static void mali_activity_enqueue(int core, int key, int activity, int pid)
88{
89 int i;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010090 int count;
91
Jon Medhurste31266f2014-08-04 15:47:44 +010092 spin_lock(&mali_activities_lock);
93 i = mali_activity_index(core, key);
94
95 count = mali_activities[i].count;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010096 BUG_ON(count < 0);
Jon Medhurste31266f2014-08-04 15:47:44 +010097 ++mali_activities[i].count;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010098 if (count) {
Jon Medhurste31266f2014-08-04 15:47:44 +010099 mali_activities[i].last_activity = activity;
100 mali_activities[i].last_pid = pid;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100101 }
Jon Medhurste31266f2014-08-04 15:47:44 +0100102 spin_unlock(&mali_activities_lock);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100103
Jon Medhurst96b56152014-10-30 18:01:15 +0000104 if (!count)
Jon Medhurste31266f2014-08-04 15:47:44 +0100105 gator_marshal_activity_switch(core, key, activity, pid);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100106}
107
Jon Medhurste31266f2014-08-04 15:47:44 +0100108static void mali_activity_stop(int core, int key)
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100109{
Jon Medhurste31266f2014-08-04 15:47:44 +0100110 int i;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100111 int count;
Jon Medhurste31266f2014-08-04 15:47:44 +0100112 int last_activity = 0;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100113 int last_pid = 0;
114
Jon Medhurste31266f2014-08-04 15:47:44 +0100115 spin_lock(&mali_activities_lock);
116 i = mali_activity_index(core, key);
117
118 if (mali_activities[i].count == 0) {
119 spin_unlock(&mali_activities_lock);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100120 return;
121 }
Jon Medhurste31266f2014-08-04 15:47:44 +0100122 --mali_activities[i].count;
123 count = mali_activities[i].count;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100124 if (count) {
Jon Medhurste31266f2014-08-04 15:47:44 +0100125 last_activity = mali_activities[i].last_activity;
126 last_pid = mali_activities[i].last_pid;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100127 }
Jon Medhurste31266f2014-08-04 15:47:44 +0100128 spin_unlock(&mali_activities_lock);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100129
Jon Medhurste31266f2014-08-04 15:47:44 +0100130 gator_marshal_activity_switch(core, key, 0, 0);
Jon Medhurst96b56152014-10-30 18:01:15 +0000131 if (count)
Jon Medhurste31266f2014-08-04 15:47:44 +0100132 gator_marshal_activity_switch(core, key, last_activity, last_pid);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100133}
134
Jon Medhurst96b56152014-10-30 18:01:15 +0000135void mali_activity_clear(struct mali_counter mali_activity[], size_t mali_activity_size)
Jon Medhurste31266f2014-08-04 15:47:44 +0100136{
137 int activity;
138 int cores;
139 int core;
140
141 for (activity = 0; activity < mali_activity_size; ++activity) {
142 cores = mali_activity[activity].cores;
Jon Medhurst96b56152014-10-30 18:01:15 +0000143 if (cores < 0)
Jon Medhurste31266f2014-08-04 15:47:44 +0100144 cores = 1;
Jon Medhurste31266f2014-08-04 15:47:44 +0100145 for (core = 0; core < cores; ++core) {
146 if (mali_activity[activity].enabled) {
Jon Medhurst96b56152014-10-30 18:01:15 +0000147 preempt_disable();
Jon Medhurste31266f2014-08-04 15:47:44 +0100148 gator_marshal_activity_switch(core, mali_activity[activity].key, 0, 0);
Jon Medhurst96b56152014-10-30 18:01:15 +0000149 preempt_enable();
Jon Medhurste31266f2014-08-04 15:47:44 +0100150 }
151 }
152 }
153}
154
155#endif
156
Jon Medhurst96b56152014-10-30 18:01:15 +0000157#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD)
Jon Medhurstd3698592013-10-10 16:48:56 +0100158#include "gator_events_mali_4xx.h"
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100159
160/*
161 * Taken from MALI_PROFILING_EVENT_CHANNEL_* in Mali DDK.
162 */
163enum {
164 EVENT_CHANNEL_SOFTWARE = 0,
165 EVENT_CHANNEL_VP0 = 1,
166 EVENT_CHANNEL_FP0 = 5,
167 EVENT_CHANNEL_FP1,
168 EVENT_CHANNEL_FP2,
169 EVENT_CHANNEL_FP3,
170 EVENT_CHANNEL_FP4,
171 EVENT_CHANNEL_FP5,
172 EVENT_CHANNEL_FP6,
173 EVENT_CHANNEL_FP7,
174 EVENT_CHANNEL_GPU = 21
175};
176
177/**
178 * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from the GPU channel
179 */
180enum {
181 EVENT_REASON_SINGLE_GPU_NONE = 0,
182 EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1,
183};
184
Jon Medhurst96b56152014-10-30 18:01:15 +0000185struct mali_counter mali_activity[2];
Jon Medhurste31266f2014-08-04 15:47:44 +0100186
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100187GATOR_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))
188{
189 unsigned int component, state;
190
Jon Medhurst96b56152014-10-30 18:01:15 +0000191 /* 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 */
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100194
195 switch (state) {
196 case EVENT_TYPE_START:
197 if (component == EVENT_CHANNEL_VP0) {
198 /* tgid = d0; pid = d1; */
Jon Medhurst96b56152014-10-30 18:01:15 +0000199 if (mali_activity[1].enabled)
Jon Medhurste31266f2014-08-04 15:47:44 +0100200 mali_activity_enqueue(0, mali_activity[1].key, 1, d1);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100201 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
202 /* tgid = d0; pid = d1; */
Jon Medhurst96b56152014-10-30 18:01:15 +0000203 if (mali_activity[0].enabled)
Jon Medhurste31266f2014-08-04 15:47:44 +0100204 mali_activity_enqueue(component - EVENT_CHANNEL_FP0, mali_activity[0].key, 1, d1);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100205 }
206 break;
207
208 case EVENT_TYPE_STOP:
209 if (component == EVENT_CHANNEL_VP0) {
Jon Medhurst96b56152014-10-30 18:01:15 +0000210 if (mali_activity[1].enabled)
Jon Medhurste31266f2014-08-04 15:47:44 +0100211 mali_activity_stop(0, mali_activity[1].key);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100212 } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) {
Jon Medhurst96b56152014-10-30 18:01:15 +0000213 if (mali_activity[0].enabled)
Jon Medhurste31266f2014-08-04 15:47:44 +0100214 mali_activity_stop(component - EVENT_CHANNEL_FP0, mali_activity[0].key);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100215 }
216 break;
217
218 case EVENT_TYPE_SINGLE:
219 if (component == EVENT_CHANNEL_GPU) {
220 unsigned int reason = (event_id & 0xffff);
221
Jon Medhurst96b56152014-10-30 18:01:15 +0000222 if (reason == EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE)
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100223 gator_events_mali_log_dvfs_event(d0, d1);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100224 }
225 break;
226
227 default:
228 break;
229 }
230}
231#endif
232
Jon Medhurst96b56152014-10-30 18:01:15 +0000233#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD)
Jon Medhurste31266f2014-08-04 15:47:44 +0100234
Jon Medhurst96b56152014-10-30 18:01:15 +0000235struct mali_counter mali_activity[3];
Jon Medhurste31266f2014-08-04 15:47:44 +0100236
Jon Medhurstd3698592013-10-10 16:48:56 +0100237#if defined(MALI_JOB_SLOTS_EVENT_CHANGED)
238GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid, unsigned char job_id))
239#else
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100240GATOR_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 +0100241#endif
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100242{
243 unsigned int component, state, unit;
Jon Medhurstd3698592013-10-10 16:48:56 +0100244#if !defined(MALI_JOB_SLOTS_EVENT_CHANGED)
245 unsigned char job_id = 0;
246#endif
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100247
Jon Medhurst96b56152014-10-30 18:01:15 +0000248 component = (event_id >> 16) & 0xFF; /* component is an 8-bit field */
249 state = (event_id >> 24) & 0xF; /* state is a 4-bit field */
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100250
251 switch (component) {
252 case 0:
253 unit = GPU_UNIT_FP;
254 break;
255 case 1:
256 unit = GPU_UNIT_VP;
257 break;
258 case 2:
259 unit = GPU_UNIT_CL;
260 break;
261 default:
262 unit = GPU_UNIT_NONE;
263 }
264
265 if (unit != GPU_UNIT_NONE) {
266 switch (state) {
267 case EVENT_TYPE_START:
Jon Medhurst96b56152014-10-30 18:01:15 +0000268 if (mali_activity[component].enabled)
Jon Medhurste31266f2014-08-04 15:47:44 +0100269 mali_activity_enqueue(0, mali_activity[component].key, 1, (pid != 0 ? pid : tgid));
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100270 break;
271 case EVENT_TYPE_STOP:
Jon Medhurst96b56152014-10-30 18:01:15 +0000272 default: /* Some jobs can be soft-stopped, so ensure that this terminates the activity trace. */
273 if (mali_activity[component].enabled)
Jon Medhurste31266f2014-08-04 15:47:44 +0100274 mali_activity_stop(0, mali_activity[component].key);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100275 break;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100276 }
277 }
278}
279#endif
280
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100281static int gator_trace_gpu_start(void)
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100282{
283 /*
284 * Returns nonzero for installation failed
285 * Absence of gpu trace points is not an error
286 */
287
Jon Medhurste31266f2014-08-04 15:47:44 +0100288#if defined(MALI_SUPPORT)
289 memset(&mali_activities, 0, sizeof(mali_activities));
290#endif
291 mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100292
Jon Medhurst96b56152014-10-30 18:01:15 +0000293#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD)
Jon Medhurste31266f2014-08-04 15:47:44 +0100294 mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity));
Jon Medhurst96b56152014-10-30 18:01:15 +0000295 if (!GATOR_REGISTER_TRACE(mali_timeline_event))
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100296 mali_timeline_trace_registered = 1;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100297#endif
298
Jon Medhurst96b56152014-10-30 18:01:15 +0000299#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD)
Jon Medhurste31266f2014-08-04 15:47:44 +0100300 mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity));
Jon Medhurst96b56152014-10-30 18:01:15 +0000301 if (!GATOR_REGISTER_TRACE(mali_job_slots_event))
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100302 mali_job_slots_trace_registered = 1;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100303#endif
304
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100305 return 0;
306}
307
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100308static void gator_trace_gpu_stop(void)
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100309{
Jon Medhurst96b56152014-10-30 18:01:15 +0000310#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD)
311 if (mali_timeline_trace_registered)
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100312 GATOR_UNREGISTER_TRACE(mali_timeline_event);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100313#endif
314
Jon Medhurst96b56152014-10-30 18:01:15 +0000315#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD)
316 if (mali_job_slots_trace_registered)
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100317 GATOR_UNREGISTER_TRACE(mali_job_slots_event);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100318#endif
319
Jon Medhurste31266f2014-08-04 15:47:44 +0100320 mali_timeline_trace_registered = mali_job_slots_trace_registered = 0;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100321}