import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / gpu / mt8127 / mali / ump / common / ump_kernel_common.c
1 /*
2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2009-2013 ARM Limited
5 * ALL RIGHTS RESERVED
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
9 */
10
11 #include "mali_kernel_common.h"
12 #include "mali_osk.h"
13 #include "mali_osk_bitops.h"
14 #include "mali_osk_list.h"
15 #include "ump_osk.h"
16 #include "ump_uk_types.h"
17 #include "ump_ukk.h"
18 #include "ump_kernel_common.h"
19 #include "ump_kernel_descriptor_mapping.h"
20 #include "ump_kernel_memory_backend.h"
21
22
23
24 /**
25 * Define the initial and maximum size of number of secure_ids on the system
26 */
27 #define UMP_SECURE_ID_TABLE_ENTRIES_INITIAL (128 )
28 #define UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM (4096 )
29
30
31 /**
32 * Define the initial and maximum size of the ump_session_data::cookies_map,
33 * which is a \ref ump_descriptor_mapping. This limits how many secure_ids
34 * may be mapped into a particular process using _ump_ukk_map_mem().
35 */
36
37 #define UMP_COOKIES_PER_SESSION_INITIAL (UMP_SECURE_ID_TABLE_ENTRIES_INITIAL )
38 #define UMP_COOKIES_PER_SESSION_MAXIMUM (UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM)
39
40 struct ump_dev device;
41
42 _mali_osk_errcode_t ump_kernel_constructor(void)
43 {
44 _mali_osk_errcode_t err;
45
46 /* Perform OS Specific initialization */
47 err = _ump_osk_init();
48 if( _MALI_OSK_ERR_OK != err ) {
49 MSG_ERR(("Failed to initiaze the UMP Device Driver"));
50 return err;
51 }
52
53 /* Init the global device */
54 _mali_osk_memset(&device, 0, sizeof(device) );
55
56 /* Create the descriptor map, which will be used for mapping secure ID to ump_dd_mem structs */
57 device.secure_id_map_lock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_UNORDERED, 0);
58 if (NULL == device.secure_id_map_lock) {
59 MSG_ERR(("Failed to create OSK lock for secure id lookup table\n"));
60 return _MALI_OSK_ERR_NOMEM;
61 }
62
63 device.secure_id_map = ump_descriptor_mapping_create(UMP_SECURE_ID_TABLE_ENTRIES_INITIAL, UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM);
64 if (NULL == device.secure_id_map) {
65 _mali_osk_mutex_term(device.secure_id_map_lock);
66 MSG_ERR(("Failed to create secure id lookup table\n"));
67 return _MALI_OSK_ERR_NOMEM;
68 }
69
70 /* Init memory backend */
71 device.backend = ump_memory_backend_create();
72 if (NULL == device.backend) {
73 MSG_ERR(("Failed to create memory backend\n"));
74 _mali_osk_mutex_term(device.secure_id_map_lock);
75 ump_descriptor_mapping_destroy(device.secure_id_map);
76 return _MALI_OSK_ERR_NOMEM;
77 }
78
79 return _MALI_OSK_ERR_OK;
80 }
81
82 void ump_kernel_destructor(void)
83 {
84 DEBUG_ASSERT_POINTER(device.secure_id_map);
85 DEBUG_ASSERT_POINTER(device.secure_id_map_lock);
86
87 _mali_osk_mutex_term(device.secure_id_map_lock);
88 device.secure_id_map_lock = NULL;
89
90 ump_descriptor_mapping_destroy(device.secure_id_map);
91 device.secure_id_map = NULL;
92
93 device.backend->shutdown(device.backend);
94 device.backend = NULL;
95
96 ump_memory_backend_destroy();
97
98 _ump_osk_term();
99 }
100
101 /** Creates a new UMP session
102 */
103 _mali_osk_errcode_t _ump_ukk_open( void** context )
104 {
105 struct ump_session_data * session_data;
106
107 /* allocated struct to track this session */
108 session_data = (struct ump_session_data *)_mali_osk_malloc(sizeof(struct ump_session_data));
109 if (NULL == session_data) {
110 MSG_ERR(("Failed to allocate ump_session_data in ump_file_open()\n"));
111 return _MALI_OSK_ERR_NOMEM;
112 }
113
114 session_data->lock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_UNORDERED, 0);
115 if( NULL == session_data->lock ) {
116 MSG_ERR(("Failed to initialize lock for ump_session_data in ump_file_open()\n"));
117 _mali_osk_free(session_data);
118 return _MALI_OSK_ERR_NOMEM;
119 }
120
121 session_data->cookies_map = ump_descriptor_mapping_create( UMP_COOKIES_PER_SESSION_INITIAL, UMP_COOKIES_PER_SESSION_MAXIMUM );
122
123 if ( NULL == session_data->cookies_map ) {
124 MSG_ERR(("Failed to create descriptor mapping for _ump_ukk_map_mem cookies\n"));
125
126 _mali_osk_mutex_term(session_data->lock);
127 _mali_osk_free( session_data );
128 return _MALI_OSK_ERR_NOMEM;
129 }
130
131 _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_list);
132
133 _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_mappings_list);
134
135 /* Since initial version of the UMP interface did not use the API_VERSION ioctl we have to assume
136 that it is this version, and not the "latest" one: UMP_IOCTL_API_VERSION
137 Current and later API versions would do an additional call to this IOCTL and update this variable
138 to the correct one.*/
139 session_data->api_version = MAKE_VERSION_ID(1);
140
141 *context = (void*)session_data;
142
143 session_data->cache_operations_ongoing = 0 ;
144 session_data->has_pending_level1_cache_flush = 0;
145
146 DBG_MSG(2, ("New session opened\n"));
147
148 return _MALI_OSK_ERR_OK;
149 }
150
151 _mali_osk_errcode_t _ump_ukk_close( void** context )
152 {
153 struct ump_session_data * session_data;
154 ump_session_memory_list_element * item;
155 ump_session_memory_list_element * tmp;
156
157 session_data = (struct ump_session_data *)*context;
158 if (NULL == session_data) {
159 MSG_ERR(("Session data is NULL in _ump_ukk_close()\n"));
160 return _MALI_OSK_ERR_INVALID_ARGS;
161 }
162
163 /* Unmap any descriptors mapped in. */
164 if (0 == _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list)) {
165 ump_memory_allocation *descriptor;
166 ump_memory_allocation *temp;
167
168 DBG_MSG(1, ("Memory mappings found on session usage list during session termination\n"));
169
170 /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */
171 _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->list_head_session_memory_mappings_list, ump_memory_allocation, list) {
172 _ump_uk_unmap_mem_s unmap_args;
173 DBG_MSG(4, ("Freeing block with phys address 0x%x size 0x%x mapped in user space at 0x%x\n",
174 descriptor->phys_addr, descriptor->size, descriptor->mapping));
175 unmap_args.ctx = (void*)session_data;
176 unmap_args.mapping = descriptor->mapping;
177 unmap_args.size = descriptor->size;
178 unmap_args._ukk_private = NULL; /* NOTE: unused */
179 unmap_args.cookie = descriptor->cookie;
180
181 /* NOTE: This modifies the list_head_session_memory_mappings_list */
182 _ump_ukk_unmap_mem( &unmap_args );
183 }
184 }
185
186 /* ASSERT that we really did free everything, because _ump_ukk_unmap_mem()
187 * can fail silently. */
188 DEBUG_ASSERT( _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list) );
189
190 _MALI_OSK_LIST_FOREACHENTRY(item, tmp, &session_data->list_head_session_memory_list, ump_session_memory_list_element, list) {
191 _mali_osk_list_del(&item->list);
192 DBG_MSG(2, ("Releasing UMP memory %u as part of file close\n", item->mem->secure_id));
193 ump_dd_reference_release(item->mem);
194 _mali_osk_free(item);
195 }
196
197 ump_descriptor_mapping_destroy( session_data->cookies_map );
198
199 _mali_osk_mutex_term(session_data->lock);
200 _mali_osk_free(session_data);
201
202 DBG_MSG(2, ("Session closed\n"));
203
204 return _MALI_OSK_ERR_OK;
205 }
206
207 _mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args )
208 {
209 struct ump_session_data * session_data;
210 ump_memory_allocation * descriptor; /* Describes current mapping of memory */
211 _mali_osk_errcode_t err;
212 unsigned long offset = 0;
213 unsigned long left;
214 ump_dd_handle handle; /* The real UMP handle for this memory. Its real datatype is ump_dd_mem* */
215 ump_dd_mem * mem; /* The real UMP memory. It is equal to the handle, but with exposed struct */
216 u32 block;
217 int map_id;
218
219 session_data = (ump_session_data *)args->ctx;
220 if( NULL == session_data ) {
221 MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n"));
222 return _MALI_OSK_ERR_INVALID_ARGS;
223 }
224
225 descriptor = (ump_memory_allocation*) _mali_osk_calloc( 1, sizeof(ump_memory_allocation));
226 if (NULL == descriptor) {
227 MSG_ERR(("ump_ukk_map_mem: descriptor allocation failed\n"));
228 return _MALI_OSK_ERR_NOMEM;
229 }
230
231 handle = ump_dd_handle_create_from_secure_id(args->secure_id);
232 if ( UMP_DD_HANDLE_INVALID == handle) {
233 _mali_osk_free(descriptor);
234 DBG_MSG(1, ("Trying to map unknown secure ID %u\n", args->secure_id));
235 return _MALI_OSK_ERR_FAULT;
236 }
237
238 mem = (ump_dd_mem*)handle;
239 DEBUG_ASSERT(mem);
240 if (mem->size_bytes != args->size) {
241 _mali_osk_free(descriptor);
242 ump_dd_reference_release(handle);
243 DBG_MSG(1, ("Trying to map too much or little. ID: %u, virtual size=%lu, UMP size: %lu\n", args->secure_id, args->size, mem->size_bytes));
244 return _MALI_OSK_ERR_FAULT;
245 }
246
247 map_id = ump_descriptor_mapping_allocate_mapping( session_data->cookies_map, (void*) descriptor );
248
249 if (map_id < 0) {
250 _mali_osk_free(descriptor);
251 ump_dd_reference_release(handle);
252 DBG_MSG(1, ("ump_ukk_map_mem: unable to allocate a descriptor_mapping for return cookie\n"));
253
254 return _MALI_OSK_ERR_NOMEM;
255 }
256
257 descriptor->size = args->size;
258 descriptor->handle = handle;
259 descriptor->phys_addr = args->phys_addr;
260 descriptor->process_mapping_info = args->_ukk_private;
261 descriptor->ump_session = session_data;
262 descriptor->cookie = (u32)map_id;
263
264 if ( mem->is_cached ) {
265 descriptor->is_cached = 1;
266 args->is_cached = 1;
267 DBG_MSG(3, ("Mapping UMP secure_id: %d as cached.\n", args->secure_id));
268 } else {
269 descriptor->is_cached = 0;
270 args->is_cached = 0;
271 DBG_MSG(3, ("Mapping UMP secure_id: %d as Uncached.\n", args->secure_id));
272 }
273
274 _mali_osk_list_init( &descriptor->list );
275
276 err = _ump_osk_mem_mapregion_init( descriptor );
277 if( _MALI_OSK_ERR_OK != err ) {
278 DBG_MSG(1, ("Failed to initialize memory mapping in _ump_ukk_map_mem(). ID: %u\n", args->secure_id));
279 ump_descriptor_mapping_free( session_data->cookies_map, map_id );
280 _mali_osk_free(descriptor);
281 ump_dd_reference_release(mem);
282 return err;
283 }
284
285 DBG_MSG(4, ("Mapping virtual to physical memory: ID: %u, size:%lu, first physical addr: 0x%08lx, number of regions: %lu\n",
286 mem->secure_id,
287 mem->size_bytes,
288 ((NULL != mem->block_array) ? mem->block_array->addr : 0),
289 mem->nr_blocks));
290
291 left = descriptor->size;
292 /* loop over all blocks and map them in */
293 for (block = 0; block < mem->nr_blocks; block++) {
294 unsigned long size_to_map;
295
296 if (left > mem->block_array[block].size) {
297 size_to_map = mem->block_array[block].size;
298 } else {
299 size_to_map = left;
300 }
301
302 if (_MALI_OSK_ERR_OK != _ump_osk_mem_mapregion_map(descriptor, offset, (u32 *)&(mem->block_array[block].addr), size_to_map ) ) {
303 DBG_MSG(1, ("WARNING: _ump_ukk_map_mem failed to map memory into userspace\n"));
304 ump_descriptor_mapping_free( session_data->cookies_map, map_id );
305 ump_dd_reference_release(mem);
306 _ump_osk_mem_mapregion_term( descriptor );
307 _mali_osk_free(descriptor);
308 return _MALI_OSK_ERR_FAULT;
309 }
310 left -= size_to_map;
311 offset += size_to_map;
312 }
313
314 /* Add to the ump_memory_allocation tracking list */
315 _mali_osk_mutex_wait(session_data->lock);
316 _mali_osk_list_add( &descriptor->list, &session_data->list_head_session_memory_mappings_list );
317 _mali_osk_mutex_signal(session_data->lock);
318
319 args->mapping = descriptor->mapping;
320 args->cookie = descriptor->cookie;
321
322 return _MALI_OSK_ERR_OK;
323 }
324
325 void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args )
326 {
327 struct ump_session_data * session_data;
328 ump_memory_allocation * descriptor;
329 ump_dd_handle handle;
330
331 session_data = (ump_session_data *)args->ctx;
332
333 if( NULL == session_data ) {
334 MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n"));
335 return;
336 }
337
338 if (0 != ump_descriptor_mapping_get( session_data->cookies_map, (int)args->cookie, (void**)&descriptor) ) {
339 MSG_ERR(("_ump_ukk_map_mem: cookie 0x%X not found for this session\n", args->cookie ));
340 return;
341 }
342
343 DEBUG_ASSERT_POINTER(descriptor);
344
345 handle = descriptor->handle;
346 if ( UMP_DD_HANDLE_INVALID == handle) {
347 DBG_MSG(1, ("WARNING: Trying to unmap unknown handle: UNKNOWN\n"));
348 return;
349 }
350
351 /* Remove the ump_memory_allocation from the list of tracked mappings */
352 _mali_osk_mutex_wait(session_data->lock);
353 _mali_osk_list_del( &descriptor->list );
354 _mali_osk_mutex_signal(session_data->lock);
355
356 ump_descriptor_mapping_free( session_data->cookies_map, (int)args->cookie );
357
358 ump_dd_reference_release(handle);
359
360 _ump_osk_mem_mapregion_term( descriptor );
361 _mali_osk_free(descriptor);
362 }
363
364 u32 _ump_ukk_report_memory_usage( void )
365 {
366 if(device.backend->stat)
367 return device.backend->stat(device.backend);
368 else
369 return 0;
370 }