tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / gpu / arm / mali400 / r5p0_rel0 / common / mali_session.c
1 /*
2  * Copyright (C) 2012-2014 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 "mali_osk.h"
12 #include "mali_osk_list.h"
13 #include "mali_session.h"
14 #include "mali_ukk.h"
15 #include "mali_memory_os_alloc.h"
16 #if TIZEN_GLES_MEM_PROFILE
17 #include "mali_kernel_sysfs.h"
18 #endif
19
20 _MALI_OSK_LIST_HEAD(mali_sessions);
21 static u32 mali_session_count = 0;
22
23 _mali_osk_spinlock_irq_t *mali_sessions_lock = NULL;
24
25 _mali_osk_errcode_t mali_session_initialize(void)
26 {
27         _MALI_OSK_INIT_LIST_HEAD(&mali_sessions);
28
29         mali_sessions_lock = _mali_osk_spinlock_irq_init(
30                                      _MALI_OSK_LOCKFLAG_ORDERED,
31                                      _MALI_OSK_LOCK_ORDER_SESSIONS);
32         if (NULL == mali_sessions_lock) {
33                 return _MALI_OSK_ERR_NOMEM;
34         }
35
36         return _MALI_OSK_ERR_OK;
37 }
38
39 void mali_session_terminate(void)
40 {
41         if (NULL != mali_sessions_lock) {
42                 _mali_osk_spinlock_irq_term(mali_sessions_lock);
43                 mali_sessions_lock = NULL;
44         }
45 }
46
47 #if TIZEN_GLES_MEM_PROFILE
48 static void mali_session_gles_mem_init(struct mali_session_data *session)
49 {
50         struct mali_session_gles_mem_profile_info *info;
51         int i;
52
53         mali_sysfs_gles_mem_profile_add((void *)session);
54
55         for (i = 0; i < MALI_MAX_GLES_MEM_TYPES; i++) {
56                 info = &(session->gles_mem_profile_info[i]);
57                 info->type = i;
58                 info->lock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_ORDERED,
59                                                 _MALI_OSK_LOCK_ORDER_SESSIONS);
60                 if (!info->lock)
61                         MALI_PRINT_ERROR(("Mutex init failure"));
62                 _MALI_OSK_INIT_LIST_HEAD(&(info->api_head));
63         }
64 }
65
66 static void mali_session_gles_mem_profile_apis_remove(
67                                 struct mali_session_gles_mem_profile_info *info)
68 {
69         struct mali_session_gles_mem_profile_api_info *api, *tmp;
70
71         _mali_osk_mutex_wait(info->lock);
72
73         _MALI_OSK_LIST_FOREACHENTRY(api, tmp, &(info->api_head),
74                         struct mali_session_gles_mem_profile_api_info, link) {
75                 _mali_osk_list_delinit(&(api->link));
76                 _mali_osk_free(api);
77         }
78
79         _mali_osk_mutex_signal(info->lock);
80 }
81
82 static void mali_session_gles_mem_deinit(struct mali_session_data *session)
83 {
84         struct mali_session_gles_mem_profile_trash_info *trash_info = NULL;
85         struct mali_session_gles_mem_profile_info *info;
86         int i;
87
88         for (i = 0; i < MALI_MAX_GLES_MEM_TYPES; i++) {
89                 info = &(session->gles_mem_profile_info[i]);
90                 if (!info->lock)
91                         continue;
92
93                 if (info->size) {
94                         trash_info =
95                         (struct mali_session_gles_mem_profile_trash_info *)
96                                 mali_sysfs_gles_mem_profile_move_to_trash(
97                                                         (void *)trash_info,
98                                                         (void *)session, i);
99                 } else
100                         mali_session_gles_mem_profile_apis_remove(info);
101
102                 _mali_osk_mutex_term(info->lock);
103         }
104
105         mali_sysfs_gles_mem_profile_remove((void *)session);
106 }
107 #endif  /* TIZEN_GLES_MEM_PROFILE */
108
109 void mali_session_add(struct mali_session_data *session)
110 {
111         mali_session_lock();
112         _mali_osk_list_add(&session->link, &mali_sessions);
113         mali_session_count++;
114         mali_session_unlock();
115
116 #if TIZEN_GLES_MEM_PROFILE
117         mali_session_gles_mem_init(session);
118 #endif
119 }
120
121 void mali_session_remove(struct mali_session_data *session)
122 {
123 #if TIZEN_GLES_MEM_PROFILE
124         mali_session_gles_mem_deinit(session);
125 #endif
126
127         mali_session_lock();
128         _mali_osk_list_delinit(&session->link);
129         mali_session_count--;
130         mali_session_unlock();
131 }
132
133 u32 mali_session_get_count(void)
134 {
135         return mali_session_count;
136 }
137
138 /*
139  * Get the max completed window jobs from all active session,
140  * which will be used in window render frame per sec calculate
141  */
142 #if defined(CONFIG_MALI_DVFS)
143 u32 mali_session_max_window_num(void)
144 {
145         struct mali_session_data *session, *tmp;
146         u32 max_window_num = 0;
147         u32 tmp_number = 0;
148
149         mali_session_lock();
150
151         MALI_SESSION_FOREACH(session, tmp, link) {
152                 tmp_number = _mali_osk_atomic_xchg(
153                                      &session->number_of_window_jobs, 0);
154                 if (max_window_num < tmp_number) {
155                         max_window_num = tmp_number;
156                 }
157         }
158
159         mali_session_unlock();
160
161         return max_window_num;
162 }
163 #endif
164
165 void mali_session_memory_tracking(_mali_osk_print_ctx *print_ctx)
166 {
167         struct mali_session_data *session, *tmp;
168         u32 mali_mem_usage;
169         u32 total_mali_mem_size;
170         u32 mali_mem_os;
171         u32 mali_mem_page;
172
173         MALI_DEBUG_ASSERT_POINTER(print_ctx);
174         mali_session_lock();
175         MALI_SESSION_FOREACH(session, tmp, link) {
176                 _mali_osk_ctxprintf(print_ctx, "  %-25s  %-10u  %-10u  %-15u  %-15u  %-10u  %-10u\n",
177                                     session->comm, session->pid,
178                                     session->mali_mem_array[MALI_MEM_OS] + session->mali_mem_array[MALI_MEM_BLOCK], session->max_mali_mem_allocated,
179                                     session->mali_mem_array[MALI_MEM_EXTERNAL], session->mali_mem_array[MALI_MEM_UMP],
180                                     session->mali_mem_array[MALI_MEM_DMA_BUF]);
181         }
182         mali_session_unlock();
183         mali_mem_usage  = _mali_ukk_report_memory_usage();
184         total_mali_mem_size = _mali_ukk_report_total_memory_size();
185         mali_mem_os = mali_mem_os_stat() + mali_mem_os_free_stat();
186         mali_mem_page = mali_mem_page_table_stat();
187         _mali_osk_ctxprintf(print_ctx, "Mali mem usage: %u\nMali mem limit: %u\nMali mem os:    %u\nMali mem page:  %u\n",
188                 mali_mem_usage, total_mali_mem_size, mali_mem_os, mali_mem_page);
189 }
190
191 #if TIZEN_GLES_MEM_PROFILE
192 void mali_session_gles_mem_profile_api_add(
193                         struct mali_session_gles_mem_profile_info *info,
194                         struct mali_session_gles_mem_profile_api_info *api,
195                         _mali_osk_list_t *head)
196 {
197         if (!info->lock)
198                 return;
199
200         _mali_osk_mutex_wait(info->lock);
201
202         _mali_osk_list_add(&(api->link), head);
203
204         _mali_osk_mutex_signal(info->lock);
205 }
206
207 static const char *mali_session_gles_mem_profile_to_str(
208                                 enum mali_session_gles_mem_profile_type type)
209 {
210         switch (type) {
211         case MALI_GLES_MEM_UNTYPED:
212                 return "mali_gles_mem Untyped";
213         case MALI_GLES_MEM_VB_IB:
214                 return "mali_gles_mem Vertex & Index buffer";
215         case MALI_GLES_MEM_TEXTURE:
216                 return "mali_gles_mem Texture";
217         case MALI_GLES_MEM_RSW:
218                 return "mali_gles_mem RSW";
219         case MALI_GLES_MEM_PLBU_HEAP:
220                 return "mali_gles_mem PLBU heap";
221         case MALI_GLES_MEM_UNTYPE_GP_CMD_LIST:
222                 return "mali_gles_mem Uuntyped GP cmd list";
223         case MALI_GLES_MEM_SHADER:
224                 return "mali_gles_mem Shader";
225         case MALI_GLES_MEM_TD:
226                 return "mali_gles_mem TD";
227         case MALI_GLES_MEM_UNTYPE_FRAME_POOL:
228                 return "mali_gles_mem Untyped frame pool";
229         case MALI_GLES_MEM_UNTYPE_SURFACE:
230                 return "mali_gles_mem Untyped surface";
231         case MALI_GLES_MEM_RT:
232                 return "mali_gles_mem Render target";
233         case MALI_GLES_MEM_VARYING:
234                 return "mali_gles_mem Varying buffer";
235         case MALI_GLES_MEM_STREAMS:
236                 return "mali_gles_mem Streams buffer";
237         case MALI_GLES_MEM_POINTER_ARRAY:
238                 return "mali_gles_mem Pointer array buffer";
239         case MALI_GLES_MEM_SLAVE_TILE_LIST:
240                 return "mali_gles_mem Slave tile list buffer";
241         case MALI_GLES_MEM_POLYGON_CMD_LIST:
242                 return "mali_gles_mem Polygon cmd list";
243         case MALI_GLES_MEM_FRAGMENT_STACK:
244                 return "mali_gles_mem Fragment stack";
245         case MALI_GLES_MEM_UNIFORM:
246                 return "mali_gles_mem Uniforms";
247         case MALI_GLES_MEM_PBUFFER:
248                 return "mali_gles_mem Pbuffer";
249         default:
250                 return "mali_gles_mem Untyped";
251         }
252 }
253
254 static void mali_session_gles_mem_profile_api_tracking(
255                                 _mali_osk_print_ctx *print_ctx,
256                                 struct mali_session_gles_mem_profile_info *info)
257 {
258         struct mali_session_gles_mem_profile_api_info *api, *tmp;
259
260         _MALI_OSK_LIST_FOREACHENTRY(api, tmp, &(info->api_head),
261                         struct mali_session_gles_mem_profile_api_info, link) {
262                 _mali_osk_ctxprintf(print_ctx, "\t| %-36s\t%-30d\n",
263                                         api->api, api->size);
264         }
265 }
266
267 s64 mali_session_gles_mem_profile_info_tracking(_mali_osk_print_ctx *print_ctx,
268                                                         void *data, bool trash)
269 {
270         struct mali_session_gles_mem_profile_trash_info *trash_info = NULL;
271         struct mali_session_gles_mem_profile_info *info;
272         struct mali_session_data *session = NULL;
273         s64 total_size = 0;
274         int i;
275
276         MALI_DEBUG_ASSERT_POINTER(print_ctx);
277         MALI_DEBUG_ASSERT_POINTER(data);
278
279         if (trash) {
280                 trash_info =
281                         (struct mali_session_gles_mem_profile_trash_info *)data;
282         } else
283                 session = (struct mali_session_data *)data;
284
285         for (i = 0; i < MALI_MAX_GLES_MEM_TYPES; i++) {
286                 if (trash)
287                         info = &(trash_info->info[i]);
288                 else
289                         info = &(session->gles_mem_profile_info[i]);
290                 if (!info->lock)
291                         continue;
292
293                 _mali_osk_mutex_wait(info->lock);
294
295                 _mali_osk_ctxprintf(print_ctx, "%-36s\t%-30lld\n",
296                                         mali_session_gles_mem_profile_to_str(
297                                                 i << MALI_GLES_MEM_SHIFT),
298                                         info->size);
299                 mali_session_gles_mem_profile_api_tracking(print_ctx, info);
300                 total_size += info->size;
301
302                 _mali_osk_mutex_signal(info->lock);
303         }
304
305         return total_size;
306 }
307 #endif  /* TIZEN_GLES_MEM_PROFILE */