tizen 2.4 release
[kernel/linux-3.0.git] / drivers / gpu / arm / mali400 / r4p0_rel0 / linux / mali_osk_profiling.c
1 /*
2  * Copyright (C) 2012 ARM Limited. All rights reserved.
3  * 
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  * 
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
9  */
10
11 #include <linux/module.h>
12
13 #include <mali_profiling_gator_api.h>
14 #include "mali_kernel_common.h"
15 #include "mali_osk.h"
16 #include "mali_ukk.h"
17 #include "mali_uk_types.h"
18 #include "mali_osk_profiling.h"
19 #include "mali_linux_trace.h"
20 #include "mali_gp.h"
21 #include "mali_pp.h"
22 #include "mali_pp_scheduler.h"
23 #include "mali_l2_cache.h"
24 #include "mali_user_settings_db.h"
25
26 _mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start)
27 {
28         if (MALI_TRUE == auto_start) {
29                 mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE);
30         }
31
32         return _MALI_OSK_ERR_OK;
33 }
34
35 void _mali_osk_profiling_term(void)
36 {
37         /* Nothing to do */
38 }
39
40 _mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit)
41 {
42         /* Nothing to do */
43         return _MALI_OSK_ERR_OK;
44 }
45
46 _mali_osk_errcode_t _mali_osk_profiling_stop(u32 *count)
47 {
48         /* Nothing to do */
49         return _MALI_OSK_ERR_OK;
50 }
51
52 u32 _mali_osk_profiling_get_count(void)
53 {
54         return 0;
55 }
56
57 _mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5])
58 {
59         /* Nothing to do */
60         return _MALI_OSK_ERR_OK;
61 }
62
63 _mali_osk_errcode_t _mali_osk_profiling_clear(void)
64 {
65         /* Nothing to do */
66         return _MALI_OSK_ERR_OK;
67 }
68
69 mali_bool _mali_osk_profiling_is_recording(void)
70 {
71         return MALI_FALSE;
72 }
73
74 mali_bool _mali_osk_profiling_have_recording(void)
75 {
76         return MALI_FALSE;
77 }
78
79 void _mali_osk_profiling_report_sw_counters(u32 *counters)
80 {
81         trace_mali_sw_counters(_mali_osk_get_pid(), _mali_osk_get_tid(), NULL, counters);
82 }
83
84
85 _mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args)
86 {
87         return _mali_osk_profiling_start(&args->limit);
88 }
89
90 _mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args)
91 {
92         /* Always add process and thread identificator in the first two data elements for events from user space */
93         _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]);
94
95         return _MALI_OSK_ERR_OK;
96 }
97
98 _mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args)
99 {
100         return _mali_osk_profiling_stop(&args->count);
101 }
102
103 _mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args)
104 {
105         return _mali_osk_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data);
106 }
107
108 _mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args)
109 {
110         return _mali_osk_profiling_clear();
111 }
112
113 _mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args)
114 {
115         _mali_osk_profiling_report_sw_counters(args->counters);
116         return _MALI_OSK_ERR_OK;
117 }
118
119 /**
120  * Called by gator.ko to set HW counters
121  *
122  * @param counter_id The counter ID.
123  * @param event_id Event ID that the counter should count (HW counter value from TRM).
124  *
125  * @return 1 on success, 0 on failure.
126  */
127 int _mali_profiling_set_event(u32 counter_id, s32 event_id)
128 {
129         if (COUNTER_VP_0_C0 == counter_id) {
130                 mali_gp_job_set_gp_counter_src0(event_id);
131         } else if (COUNTER_VP_0_C1 == counter_id) {
132                 mali_gp_job_set_gp_counter_src1(event_id);
133         } else if (COUNTER_FP_0_C0 <= counter_id && COUNTER_FP_7_C1 >= counter_id) {
134                 /*
135                  * Two compatibility notes for this function:
136                  *
137                  * 1) Previously the DDK allowed per core counters.
138                  *
139                  *    This did not make much sense on Mali-450 with the "virtual PP core" concept,
140                  *    so this option was removed, and only the same pair of HW counters was allowed on all cores,
141                  *    beginning with r3p2 release.
142                  *
143                  *    Starting with r4p0, it is now possible to set different HW counters for the different sub jobs.
144                  *    This should be almost the same, since sub job 0 is designed to run on core 0,
145                  *    sub job 1 on core 1, and so on.
146                  *
147                  *    The scheduling of PP sub jobs is not predictable, and this often led to situations where core 0 ran 2
148                  *    sub jobs, while for instance core 1 ran zero. Having the counters set per sub job would thus increase
149                  *    the predictability of the returned data (as you would be guaranteed data for all the selected HW counters).
150                  *
151                  *    PS: Core scaling needs to be disabled in order to use this reliably (goes for both solutions).
152                  *
153                  *    The framework/#defines with Gator still indicates that the counter is for a particular core,
154                  *    but this is internally used as a sub job ID instead (no translation needed).
155                  *
156                  *  2) Global/default vs per sub job counters
157                  *
158                  *     Releases before r3p2 had only per PP core counters.
159                  *     r3p2 releases had only one set of default/global counters which applied to all PP cores
160                  *     Starting with r4p0, we have both a set of default/global counters,
161                  *     and individual counters per sub job (equal to per core).
162                  *
163                  *     To keep compatibility with Gator/DS-5/streamline, the following scheme is used:
164                  *
165                  *     r3p2 release; only counters set for core 0 is handled,
166                  *     this is applied as the default/global set of counters, and will thus affect all cores.
167                  *
168                  *     r4p0 release; counters set for core 0 is applied as both the global/default set of counters,
169                  *     and counters for sub job 0.
170                  *     Counters set for core 1-7 is only applied for the corresponding sub job.
171                  *
172                  *     This should allow the DS-5/Streamline GUI to have a simple mode where it only allows setting the
173                  *     values for core 0, and thus this will be applied to all PP sub jobs/cores.
174                  *     Advanced mode will also be supported, where individual pairs of HW counters can be selected.
175                  *
176                  *     The GUI will (until it is updated) still refer to cores instead of sub jobs, but this is probably
177                  *     something we can live with!
178                  *
179                  *     Mali-450 note: Each job is not divided into a deterministic number of sub jobs, as the HW DLBU
180                  *     automatically distributes the load between whatever number of cores is available at this particular time.
181                  *     A normal PP job on Mali-450 is thus considered a single (virtual) job, and it will thus only be possible
182                  *     to use a single pair of HW counters (even if the job ran on multiple PP cores).
183                  *     In other words, only the global/default pair of PP HW counters will be used for normal Mali-450 jobs.
184                  */
185                 u32 sub_job = (counter_id - COUNTER_FP_0_C0) >> 1;
186                 u32 counter_src = (counter_id - COUNTER_FP_0_C0) & 1;
187                 if (0 == counter_src) {
188                         mali_pp_job_set_pp_counter_sub_job_src0(sub_job, event_id);
189                         if (0 == sub_job) {
190                                 mali_pp_job_set_pp_counter_global_src0(event_id);
191                         }
192                 } else {
193                         mali_pp_job_set_pp_counter_sub_job_src1(sub_job, event_id);
194                         if (0 == sub_job) {
195                                 mali_pp_job_set_pp_counter_global_src1(event_id);
196                         }
197                 }
198         } else if (COUNTER_L2_0_C0 <= counter_id && COUNTER_L2_2_C1 >= counter_id) {
199                 u32 core_id = (counter_id - COUNTER_L2_0_C0) >> 1;
200                 struct mali_l2_cache_core* l2_cache_core = mali_l2_cache_core_get_glob_l2_core(core_id);
201
202                 if (NULL != l2_cache_core) {
203                         u32 counter_src = (counter_id - COUNTER_L2_0_C0) & 1;
204                         if (0 == counter_src) {
205                                 mali_l2_cache_core_set_counter_src0(l2_cache_core, event_id);
206                         } else {
207                                 mali_l2_cache_core_set_counter_src1(l2_cache_core, event_id);
208                         }
209                 }
210         } else {
211                 return 0; /* Failure, unknown event */
212         }
213
214         return 1; /* success */
215 }
216
217 /**
218  * Called by gator.ko to retrieve the L2 cache counter values for all L2 cache cores.
219  * The L2 cache counters are unique in that they are polled by gator, rather than being
220  * transmitted via the tracepoint mechanism.
221  *
222  * @param values Pointer to a _mali_profiling_l2_counter_values structure where
223  *               the counter sources and values will be output
224  * @return 0 if all went well; otherwise, return the mask with the bits set for the powered off cores
225  */
226 u32 _mali_profiling_get_l2_counters(_mali_profiling_l2_counter_values *values)
227 {
228         struct mali_l2_cache_core *l2_cache;
229         u32 l2_cores_num = mali_l2_cache_core_get_glob_num_l2_cores();
230         u32 i;
231         u32 ret = 0;
232
233         MALI_DEBUG_ASSERT(l2_cores_num <= 3);
234
235         for (i = 0; i < l2_cores_num; i++) {
236                 l2_cache = mali_l2_cache_core_get_glob_l2_core(i);
237
238                 if (NULL == l2_cache) {
239                         continue;
240                 }
241
242                 if (MALI_TRUE == mali_l2_cache_lock_power_state(l2_cache)) {
243                         /* It is now safe to access the L2 cache core in order to retrieve the counters */
244                         mali_l2_cache_core_get_counter_values(l2_cache,
245                                                               &values->cores[i].source0,
246                                                               &values->cores[i].value0,
247                                                               &values->cores[i].source1,
248                                                               &values->cores[i].value1);
249                 } else {
250                         /* The core was not available, set the right bit in the mask. */
251                         ret |= (1 << i);
252                 }
253                 mali_l2_cache_unlock_power_state(l2_cache);
254         }
255
256         return ret;
257 }
258
259 /**
260  * Called by gator to control the production of profiling information at runtime.
261  */
262 void _mali_profiling_control(u32 action, u32 value)
263 {
264         switch(action) {
265         case FBDUMP_CONTROL_ENABLE:
266                 mali_set_user_setting(_MALI_UK_USER_SETTING_COLORBUFFER_CAPTURE_ENABLED, (value == 0 ? MALI_FALSE : MALI_TRUE));
267                 break;
268         case FBDUMP_CONTROL_RATE:
269                 mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_N_FRAMES, value);
270                 break;
271         case SW_COUNTER_ENABLE:
272                 mali_set_user_setting(_MALI_UK_USER_SETTING_SW_COUNTER_ENABLED, value);
273                 break;
274         case FBDUMP_CONTROL_RESIZE_FACTOR:
275                 mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_RESIZE_FACTOR, value);
276                 break;
277         default:
278                 break;  /* Ignore unimplemented actions */
279         }
280 }
281
282 /**
283  * Called by gator to get mali api version.
284  */
285 u32 _mali_profiling_get_api_version(void)
286 {
287         return MALI_PROFILING_API_VERSION;
288 }
289
290 /**
291 * Called by gator to get the data about Mali instance in use:
292 * product id, version, number of cores
293 */
294 void _mali_profiling_get_mali_version(struct _mali_profiling_mali_version *values)
295 {
296         values->mali_product_id = (u32)mali_kernel_core_get_product_id();
297         values->mali_version_major = mali_kernel_core_get_gpu_major_version();
298         values->mali_version_minor = mali_kernel_core_get_gpu_minor_version();
299         values->num_of_l2_cores = mali_l2_cache_core_get_glob_num_l2_cores();
300         values->num_of_fp_cores = mali_pp_scheduler_get_num_cores_total();
301         values->num_of_vp_cores = 1;
302 }
303
304 EXPORT_SYMBOL(_mali_profiling_set_event);
305 EXPORT_SYMBOL(_mali_profiling_get_l2_counters);
306 EXPORT_SYMBOL(_mali_profiling_control);
307 EXPORT_SYMBOL(_mali_profiling_get_api_version);
308 EXPORT_SYMBOL(_mali_profiling_get_mali_version);