2 * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
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.
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.
11 #include "mali_kernel_common.h"
12 #include "mali_session.h"
14 #include "mali_osk_mali.h"
16 #include "mali_kernel_core.h"
17 #include "mali_memory.h"
18 #include "mali_mem_validation.h"
20 #include "mali_mmu_page_directory.h"
21 #include "mali_dlbu.h"
22 #include "mali_broadcast.h"
25 #include "mali_gp_scheduler.h"
26 #include "mali_pp_scheduler.h"
27 #include "mali_group.h"
30 #include "mali_scheduler.h"
31 #include "mali_kernel_utilization.h"
32 #include "mali_l2_cache.h"
33 #if defined(CONFIG_MALI400_PROFILING)
34 #include "mali_osk_profiling.h"
36 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
37 #include "mali_profiling_internal.h"
41 /* Mali GPU memory. Real values come from module parameter or from device specific data */
42 int mali_dedicated_mem_start = 0;
43 int mali_dedicated_mem_size = 0;
44 int mali_shared_mem_size = 0;
46 /* Frame buffer memory to be accessible by Mali GPU */
47 int mali_fb_start = 0;
50 /** Start profiling from module load? */
51 int mali_boot_profiling = 0;
53 /** Limits for the number of PP cores behind each L2 cache. */
54 int mali_max_pp_cores_group_1 = 0xFF;
55 int mali_max_pp_cores_group_2 = 0xFF;
57 int mali_inited_pp_cores_group_1 = 0;
58 int mali_inited_pp_cores_group_2 = 0;
60 static _mali_product_id_t global_product_id = _MALI_PRODUCT_ID_UNKNOWN;
61 static u32 global_gpu_base_address = 0;
62 static u32 global_gpu_major_version = 0;
63 static u32 global_gpu_minor_version = 0;
66 static u32 first_pp_offset = 0;
68 #define HANG_CHECK_MSECS_DEFAULT 500 /* 500 ms */
69 #define WATCHDOG_MSECS_DEFAULT 4000 /* 4 s */
72 int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT;
73 int mali_hang_check_interval = HANG_CHECK_MSECS_DEFAULT;
75 static _mali_osk_errcode_t mali_parse_product_info(void)
78 * Mali-200 has the PP core first, while Mali-300, Mali-400 and Mali-450 have the GP core first.
79 * Look at the version register for the first PP core in order to determine the GPU HW revision.
83 _mali_osk_resource_t first_pp_resource;
85 global_gpu_base_address = _mali_osk_resource_base_address();
86 if (0 == global_gpu_base_address)
88 return _MALI_OSK_ERR_ITEM_NOT_FOUND;
91 /* Find out where the first PP core is located */
92 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x8000, NULL))
94 /* Mali-300/400/450 */
95 first_pp_offset = 0x8000;
100 first_pp_offset = 0x0000;
103 /* Find the first PP core resource (again) */
104 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + first_pp_offset, &first_pp_resource))
106 /* Create a dummy PP object for this core so that we can read the version register */
107 struct mali_group *group = mali_group_create(NULL, NULL, NULL);
110 struct mali_pp_core *pp_core = mali_pp_create(&first_pp_resource, group, MALI_FALSE);
113 u32 pp_version = mali_pp_core_get_version(pp_core);
114 mali_group_delete(group);
116 global_gpu_major_version = (pp_version >> 8) & 0xFF;
117 global_gpu_minor_version = pp_version & 0xFF;
119 switch (pp_version >> 16)
121 case MALI200_PP_PRODUCT_ID:
122 global_product_id = _MALI_PRODUCT_ID_MALI200;
123 MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-200 r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
125 case MALI300_PP_PRODUCT_ID:
126 global_product_id = _MALI_PRODUCT_ID_MALI300;
127 MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-300 r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
129 case MALI400_PP_PRODUCT_ID:
130 global_product_id = _MALI_PRODUCT_ID_MALI400;
131 MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-400 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
133 case MALI450_PP_PRODUCT_ID:
134 global_product_id = _MALI_PRODUCT_ID_MALI450;
135 MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-450 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
138 MALI_DEBUG_PRINT(2, ("Found unknown Mali GPU (r%up%u)\n", global_gpu_major_version, global_gpu_minor_version));
139 return _MALI_OSK_ERR_FAULT;
142 return _MALI_OSK_ERR_OK;
146 MALI_PRINT_ERROR(("Failed to create initial PP object\n"));
151 MALI_PRINT_ERROR(("Failed to create initial group object\n"));
156 MALI_PRINT_ERROR(("First PP core not specified in config file\n"));
159 return _MALI_OSK_ERR_FAULT;
163 void mali_resource_count(u32 *pp_count, u32 *l2_count)
168 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x08000, NULL))
172 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0A000, NULL))
176 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0C000, NULL))
180 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0E000, NULL))
184 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x28000, NULL))
188 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2A000, NULL))
192 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2C000, NULL))
196 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2E000, NULL))
201 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, NULL))
205 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, NULL))
209 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, NULL))
215 static void mali_delete_l2_cache_cores(void)
218 u32 number_of_l2_ccores = mali_l2_cache_core_get_glob_num_l2_cores();
220 for (i = 0; i < number_of_l2_ccores; i++)
222 mali_l2_cache_delete(mali_l2_cache_core_get_glob_l2_core(i));
226 static _mali_osk_errcode_t mali_create_l2_cache_core(_mali_osk_resource_t *resource)
228 if (NULL != resource)
230 struct mali_l2_cache_core *l2_cache;
232 MALI_DEBUG_PRINT(3, ("Found L2 cache %s\n", resource->description));
234 l2_cache = mali_l2_cache_create(resource);
235 if (NULL == l2_cache)
237 MALI_PRINT_ERROR(("Failed to create L2 cache object\n"));
238 return _MALI_OSK_ERR_FAULT;
241 MALI_DEBUG_PRINT(3, ("Created L2 cache core object\n"));
243 return _MALI_OSK_ERR_OK;
246 static _mali_osk_errcode_t mali_parse_config_l2_cache(void)
248 if (_MALI_PRODUCT_ID_MALI200 == global_product_id)
250 /* Create dummy L2 cache - nothing happens here!!! */
251 return mali_create_l2_cache_core(NULL);
253 else if (_MALI_PRODUCT_ID_MALI300 == global_product_id || _MALI_PRODUCT_ID_MALI400 == global_product_id)
255 _mali_osk_resource_t l2_resource;
256 if (_MALI_OSK_ERR_OK != _mali_osk_resource_find(global_gpu_base_address + 0x1000, &l2_resource))
258 MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache in config file\n"));
259 return _MALI_OSK_ERR_FAULT;
262 return mali_create_l2_cache_core(&l2_resource);
264 else if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
267 * L2 for GP at 0x10000
268 * L2 for PP0-3 at 0x01000
269 * L2 for PP4-7 at 0x11000 (optional)
272 _mali_osk_resource_t l2_gp_resource;
273 _mali_osk_resource_t l2_pp_grp0_resource;
274 _mali_osk_resource_t l2_pp_grp1_resource;
276 /* Make cluster for GP's L2 */
277 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, &l2_gp_resource))
279 _mali_osk_errcode_t ret;
280 MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for GP\n"));
281 ret = mali_create_l2_cache_core(&l2_gp_resource);
282 if (_MALI_OSK_ERR_OK != ret)
289 MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for GP in config file\n"));
290 return _MALI_OSK_ERR_FAULT;
293 /* Make cluster for first PP core group */
294 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, &l2_pp_grp0_resource))
296 _mali_osk_errcode_t ret;
297 MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 0\n"));
298 ret = mali_create_l2_cache_core(&l2_pp_grp0_resource);
299 if (_MALI_OSK_ERR_OK != ret)
306 MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for PP group 0 in config file\n"));
307 return _MALI_OSK_ERR_FAULT;
310 /* Second PP core group is optional, don't fail if we don't find it */
311 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, &l2_pp_grp1_resource))
313 _mali_osk_errcode_t ret;
314 MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 1\n"));
315 ret = mali_create_l2_cache_core(&l2_pp_grp1_resource);
316 if (_MALI_OSK_ERR_OK != ret)
323 return _MALI_OSK_ERR_OK;
326 static _mali_osk_errcode_t mali_create_group(struct mali_l2_cache_core *cache,
327 _mali_osk_resource_t *resource_mmu,
328 _mali_osk_resource_t *resource_gp,
329 _mali_osk_resource_t *resource_pp)
331 struct mali_mmu_core *mmu;
332 struct mali_group *group;
334 MALI_DEBUG_PRINT(3, ("Starting new group for MMU %s\n", resource_mmu->description));
336 /* Create the group object */
337 group = mali_group_create(cache, NULL, NULL);
340 MALI_PRINT_ERROR(("Failed to create group object for MMU %s\n", resource_mmu->description));
341 return _MALI_OSK_ERR_FAULT;
344 /* Create the MMU object inside group */
345 mmu = mali_mmu_create(resource_mmu, group, MALI_FALSE);
348 MALI_PRINT_ERROR(("Failed to create MMU object\n"));
349 mali_group_delete(group);
350 return _MALI_OSK_ERR_FAULT;
353 if (NULL != resource_gp)
355 /* Create the GP core object inside this group */
356 struct mali_gp_core *gp_core = mali_gp_create(resource_gp, group);
359 /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
360 MALI_PRINT_ERROR(("Failed to create GP object\n"));
361 mali_group_delete(group);
362 return _MALI_OSK_ERR_FAULT;
366 if (NULL != resource_pp)
368 struct mali_pp_core *pp_core;
370 /* Create the PP core object inside this group */
371 pp_core = mali_pp_create(resource_pp, group, MALI_FALSE);
374 /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
375 MALI_PRINT_ERROR(("Failed to create PP object\n"));
376 mali_group_delete(group);
377 return _MALI_OSK_ERR_FAULT;
382 mali_group_reset(group);
384 return _MALI_OSK_ERR_OK;
387 static _mali_osk_errcode_t mali_create_virtual_group(_mali_osk_resource_t *resource_mmu_pp_bcast,
388 _mali_osk_resource_t *resource_pp_bcast,
389 _mali_osk_resource_t *resource_dlbu,
390 _mali_osk_resource_t *resource_bcast)
392 struct mali_mmu_core *mmu_pp_bcast_core;
393 struct mali_pp_core *pp_bcast_core;
394 struct mali_dlbu_core *dlbu_core;
395 struct mali_bcast_unit *bcast_core;
396 struct mali_group *group;
398 MALI_DEBUG_PRINT(2, ("Starting new virtual group for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description));
400 /* Create the DLBU core object */
401 dlbu_core = mali_dlbu_create(resource_dlbu);
402 if (NULL == dlbu_core)
404 MALI_PRINT_ERROR(("Failed to create DLBU object \n"));
405 return _MALI_OSK_ERR_FAULT;
408 /* Create the Broadcast unit core */
409 bcast_core = mali_bcast_unit_create(resource_bcast);
410 if (NULL == bcast_core)
412 MALI_PRINT_ERROR(("Failed to create Broadcast unit object!\n"));
413 mali_dlbu_delete(dlbu_core);
414 return _MALI_OSK_ERR_FAULT;
417 /* Create the group object */
418 group = mali_group_create(NULL, dlbu_core, bcast_core);
421 MALI_PRINT_ERROR(("Failed to create group object for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description));
422 mali_bcast_unit_delete(bcast_core);
423 mali_dlbu_delete(dlbu_core);
424 return _MALI_OSK_ERR_FAULT;
427 /* Create the MMU object inside group */
428 mmu_pp_bcast_core = mali_mmu_create(resource_mmu_pp_bcast, group, MALI_TRUE);
429 if (NULL == mmu_pp_bcast_core)
431 MALI_PRINT_ERROR(("Failed to create MMU PP broadcast object\n"));
432 mali_group_delete(group);
433 return _MALI_OSK_ERR_FAULT;
436 /* Create the PP core object inside this group */
437 pp_bcast_core = mali_pp_create(resource_pp_bcast, group, MALI_TRUE);
438 if (NULL == pp_bcast_core)
440 /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
441 MALI_PRINT_ERROR(("Failed to create PP object\n"));
442 mali_group_delete(group);
443 return _MALI_OSK_ERR_FAULT;
446 return _MALI_OSK_ERR_OK;
449 static _mali_osk_errcode_t mali_parse_config_groups(void)
451 if (_MALI_PRODUCT_ID_MALI200 == global_product_id)
453 _mali_osk_errcode_t err;
454 _mali_osk_resource_t resource_gp;
455 _mali_osk_resource_t resource_pp;
456 _mali_osk_resource_t resource_mmu;
458 MALI_DEBUG_ASSERT(1 == mali_l2_cache_core_get_glob_num_l2_cores());
460 if (_MALI_OSK_ERR_OK != _mali_osk_resource_find(global_gpu_base_address + 0x02000, &resource_gp) ||
461 _MALI_OSK_ERR_OK != _mali_osk_resource_find(global_gpu_base_address + 0x00000, &resource_pp) ||
462 _MALI_OSK_ERR_OK != _mali_osk_resource_find(global_gpu_base_address + 0x03000, &resource_mmu))
464 /* Missing mandatory core(s) */
465 return _MALI_OSK_ERR_FAULT;
468 err = mali_create_group(mali_l2_cache_core_get_glob_l2_core(0), &resource_mmu, &resource_gp, &resource_pp);
469 if (err == _MALI_OSK_ERR_OK)
471 mali_inited_pp_cores_group_1++;
472 mali_max_pp_cores_group_1 = mali_inited_pp_cores_group_1; /* always 1 */
473 mali_max_pp_cores_group_2 = mali_inited_pp_cores_group_2; /* always zero */
478 else if (_MALI_PRODUCT_ID_MALI300 == global_product_id ||
479 _MALI_PRODUCT_ID_MALI400 == global_product_id ||
480 _MALI_PRODUCT_ID_MALI450 == global_product_id)
482 _mali_osk_errcode_t err;
483 int cluster_id_gp = 0;
484 int cluster_id_pp_grp0 = 0;
485 int cluster_id_pp_grp1 = 0;
488 _mali_osk_resource_t resource_gp;
489 _mali_osk_resource_t resource_gp_mmu;
490 _mali_osk_resource_t resource_pp[8];
491 _mali_osk_resource_t resource_pp_mmu[8];
492 _mali_osk_resource_t resource_pp_mmu_bcast;
493 _mali_osk_resource_t resource_pp_bcast;
494 _mali_osk_resource_t resource_dlbu;
495 _mali_osk_resource_t resource_bcast;
496 _mali_osk_errcode_t resource_gp_found;
497 _mali_osk_errcode_t resource_gp_mmu_found;
498 _mali_osk_errcode_t resource_pp_found[8];
499 _mali_osk_errcode_t resource_pp_mmu_found[8];
500 _mali_osk_errcode_t resource_pp_mmu_bcast_found;
501 _mali_osk_errcode_t resource_pp_bcast_found;
502 _mali_osk_errcode_t resource_dlbu_found;
503 _mali_osk_errcode_t resource_bcast_found;
505 if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
507 /* Mali-450 have separate L2s for GP, and PP core group(s) */
508 cluster_id_pp_grp0 = 1;
509 cluster_id_pp_grp1 = 2;
512 resource_gp_found = _mali_osk_resource_find(global_gpu_base_address + 0x00000, &resource_gp);
513 resource_gp_mmu_found = _mali_osk_resource_find(global_gpu_base_address + 0x03000, &resource_gp_mmu);
514 resource_pp_found[0] = _mali_osk_resource_find(global_gpu_base_address + 0x08000, &(resource_pp[0]));
515 resource_pp_found[1] = _mali_osk_resource_find(global_gpu_base_address + 0x0A000, &(resource_pp[1]));
516 resource_pp_found[2] = _mali_osk_resource_find(global_gpu_base_address + 0x0C000, &(resource_pp[2]));
517 resource_pp_found[3] = _mali_osk_resource_find(global_gpu_base_address + 0x0E000, &(resource_pp[3]));
518 resource_pp_found[4] = _mali_osk_resource_find(global_gpu_base_address + 0x28000, &(resource_pp[4]));
519 resource_pp_found[5] = _mali_osk_resource_find(global_gpu_base_address + 0x2A000, &(resource_pp[5]));
520 resource_pp_found[6] = _mali_osk_resource_find(global_gpu_base_address + 0x2C000, &(resource_pp[6]));
521 resource_pp_found[7] = _mali_osk_resource_find(global_gpu_base_address + 0x2E000, &(resource_pp[7]));
522 resource_pp_mmu_found[0] = _mali_osk_resource_find(global_gpu_base_address + 0x04000, &(resource_pp_mmu[0]));
523 resource_pp_mmu_found[1] = _mali_osk_resource_find(global_gpu_base_address + 0x05000, &(resource_pp_mmu[1]));
524 resource_pp_mmu_found[2] = _mali_osk_resource_find(global_gpu_base_address + 0x06000, &(resource_pp_mmu[2]));
525 resource_pp_mmu_found[3] = _mali_osk_resource_find(global_gpu_base_address + 0x07000, &(resource_pp_mmu[3]));
526 resource_pp_mmu_found[4] = _mali_osk_resource_find(global_gpu_base_address + 0x1C000, &(resource_pp_mmu[4]));
527 resource_pp_mmu_found[5] = _mali_osk_resource_find(global_gpu_base_address + 0x1D000, &(resource_pp_mmu[5]));
528 resource_pp_mmu_found[6] = _mali_osk_resource_find(global_gpu_base_address + 0x1E000, &(resource_pp_mmu[6]));
529 resource_pp_mmu_found[7] = _mali_osk_resource_find(global_gpu_base_address + 0x1F000, &(resource_pp_mmu[7]));
532 if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
534 resource_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x13000, &resource_bcast);
535 resource_dlbu_found = _mali_osk_resource_find(global_gpu_base_address + 0x14000, &resource_dlbu);
536 resource_pp_mmu_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x15000, &resource_pp_mmu_bcast);
537 resource_pp_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x16000, &resource_pp_bcast);
539 if (_MALI_OSK_ERR_OK != resource_bcast_found ||
540 _MALI_OSK_ERR_OK != resource_dlbu_found ||
541 _MALI_OSK_ERR_OK != resource_pp_mmu_bcast_found ||
542 _MALI_OSK_ERR_OK != resource_pp_bcast_found)
544 /* Missing mandatory core(s) for Mali-450 */
545 MALI_DEBUG_PRINT(2, ("Missing mandatory resources, Mali-450 needs DLBU, Broadcast unit, virtual PP core and virtual MMU\n"));
546 return _MALI_OSK_ERR_FAULT;
550 if (_MALI_OSK_ERR_OK != resource_gp_found ||
551 _MALI_OSK_ERR_OK != resource_gp_mmu_found ||
552 _MALI_OSK_ERR_OK != resource_pp_found[0] ||
553 _MALI_OSK_ERR_OK != resource_pp_mmu_found[0])
555 /* Missing mandatory core(s) */
556 MALI_DEBUG_PRINT(2, ("Missing mandatory resource, need at least one GP and one PP, both with a separate MMU\n"));
557 return _MALI_OSK_ERR_FAULT;
560 MALI_DEBUG_ASSERT(1 <= mali_l2_cache_core_get_glob_num_l2_cores());
561 err = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_gp), &resource_gp_mmu, &resource_gp, NULL);
562 if (err != _MALI_OSK_ERR_OK)
567 /* Create group for first (and mandatory) PP core */
568 MALI_DEBUG_ASSERT(mali_l2_cache_core_get_glob_num_l2_cores() >= (cluster_id_pp_grp0 + 1)); /* >= 1 on Mali-300 and Mali-400, >= 2 on Mali-450 */
569 err = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[0], NULL, &resource_pp[0]);
570 if (err != _MALI_OSK_ERR_OK)
575 mali_inited_pp_cores_group_1++;
577 /* Create groups for rest of the cores in the first PP core group */
578 for (i = 1; i < 4; i++) /* First half of the PP cores belong to first core group */
580 if (mali_inited_pp_cores_group_1 < mali_max_pp_cores_group_1)
582 if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[i])
584 err = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[i], NULL, &resource_pp[i]);
585 if (err != _MALI_OSK_ERR_OK)
589 mali_inited_pp_cores_group_1++;
594 /* Create groups for cores in the second PP core group */
595 for (i = 4; i < 8; i++) /* Second half of the PP cores belong to second core group */
597 if (mali_inited_pp_cores_group_2 < mali_max_pp_cores_group_2)
599 if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[i])
601 MALI_DEBUG_ASSERT(mali_l2_cache_core_get_glob_num_l2_cores() >= 2); /* Only Mali-450 have a second core group */
602 err = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp1), &resource_pp_mmu[i], NULL, &resource_pp[i]);
603 if (err != _MALI_OSK_ERR_OK)
607 mali_inited_pp_cores_group_2++;
612 if(_MALI_PRODUCT_ID_MALI450 == global_product_id)
614 err = mali_create_virtual_group(&resource_pp_mmu_bcast, &resource_pp_bcast, &resource_dlbu, &resource_bcast);
615 if (_MALI_OSK_ERR_OK != err)
621 mali_max_pp_cores_group_1 = mali_inited_pp_cores_group_1;
622 mali_max_pp_cores_group_2 = mali_inited_pp_cores_group_2;
623 MALI_DEBUG_PRINT(2, ("%d+%d PP cores initialized\n", mali_inited_pp_cores_group_1, mali_inited_pp_cores_group_2));
625 return _MALI_OSK_ERR_OK;
628 /* No known HW core */
629 return _MALI_OSK_ERR_FAULT;
632 static _mali_osk_errcode_t mali_parse_config_pmu(void)
634 _mali_osk_resource_t resource_pmu;
636 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x02000, &resource_pmu))
638 u32 number_of_pp_cores = 0;
639 u32 number_of_l2_caches = 0;
641 mali_resource_count(&number_of_pp_cores, &number_of_l2_caches);
643 if (NULL == mali_pmu_create(&resource_pmu, number_of_pp_cores, number_of_l2_caches))
645 return _MALI_OSK_ERR_FAULT;
649 /* It's ok if the PMU doesn't exist */
650 return _MALI_OSK_ERR_OK;
653 static _mali_osk_errcode_t mali_parse_config_memory(void)
655 _mali_osk_errcode_t ret;
657 if (0 == mali_dedicated_mem_start && 0 == mali_dedicated_mem_size && 0 == mali_shared_mem_size)
659 /* Memory settings are not overridden by module parameters, so use device settings */
660 struct _mali_osk_device_data data = { 0, };
662 if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data))
664 /* Use device specific settings (if defined) */
665 mali_dedicated_mem_start = data.dedicated_mem_start;
666 mali_dedicated_mem_size = data.dedicated_mem_size;
667 mali_shared_mem_size = data.shared_mem_size;
670 if (0 == mali_dedicated_mem_start && 0 == mali_dedicated_mem_size && 0 == mali_shared_mem_size)
672 /* No GPU memory specified */
673 return _MALI_OSK_ERR_INVALID_ARGS;
676 MALI_DEBUG_PRINT(2, ("Using device defined memory settings (dedicated: 0x%08X@0x%08X, shared: 0x%08X)\n",
677 mali_dedicated_mem_size, mali_dedicated_mem_start, mali_shared_mem_size));
681 MALI_DEBUG_PRINT(2, ("Using module defined memory settings (dedicated: 0x%08X@0x%08X, shared: 0x%08X)\n",
682 mali_dedicated_mem_size, mali_dedicated_mem_start, mali_shared_mem_size));
685 if (0 < mali_dedicated_mem_size && 0 != mali_dedicated_mem_start)
687 /* Dedicated memory */
688 ret = mali_memory_core_resource_dedicated_memory(mali_dedicated_mem_start, mali_dedicated_mem_size);
689 if (_MALI_OSK_ERR_OK != ret)
691 MALI_PRINT_ERROR(("Failed to register dedicated memory\n"));
692 mali_memory_terminate();
697 if (0 < mali_shared_mem_size)
699 /* Shared OS memory */
700 ret = mali_memory_core_resource_os_memory(mali_shared_mem_size);
701 if (_MALI_OSK_ERR_OK != ret)
703 MALI_PRINT_ERROR(("Failed to register shared OS memory\n"));
704 mali_memory_terminate();
709 if (0 == mali_fb_start && 0 == mali_fb_size)
711 /* Frame buffer settings are not overridden by module parameters, so use device settings */
712 struct _mali_osk_device_data data = { 0, };
714 if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data))
716 /* Use device specific settings (if defined) */
717 mali_fb_start = data.fb_start;
718 mali_fb_size = data.fb_size;
721 MALI_DEBUG_PRINT(2, ("Using device defined frame buffer settings (0x%08X@0x%08X)\n",
722 mali_fb_size, mali_fb_start));
726 MALI_DEBUG_PRINT(2, ("Using module defined frame buffer settings (0x%08X@0x%08X)\n",
727 mali_fb_size, mali_fb_start));
730 if (0 != mali_fb_size)
732 /* Register frame buffer */
733 ret = mali_mem_validation_add_range(mali_fb_start, mali_fb_size);
734 if (_MALI_OSK_ERR_OK != ret)
736 MALI_PRINT_ERROR(("Failed to register frame buffer memory region\n"));
737 mali_memory_terminate();
742 return _MALI_OSK_ERR_OK;
745 _mali_osk_errcode_t mali_initialize_subsystems(void)
747 _mali_osk_errcode_t err;
749 err = mali_session_initialize();
750 if (_MALI_OSK_ERR_OK != err) goto session_init_failed;
752 #if defined(CONFIG_MALI400_PROFILING)
753 err = _mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE);
754 if (_MALI_OSK_ERR_OK != err)
756 /* No biggie if we wheren't able to initialize the profiling */
757 MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n"));
761 err = mali_memory_initialize();
762 if (_MALI_OSK_ERR_OK != err) goto memory_init_failed;
764 /* Configure memory early. Memory allocation needed for mali_mmu_initialize. */
765 err = mali_parse_config_memory();
766 if (_MALI_OSK_ERR_OK != err) goto parse_memory_config_failed;
768 /* Initialize the MALI PMU */
769 err = mali_parse_config_pmu();
770 if (_MALI_OSK_ERR_OK != err) goto parse_pmu_config_failed;
772 /* Initialize the power management module */
773 err = mali_pm_initialize();
774 if (_MALI_OSK_ERR_OK != err) goto pm_init_failed;
776 /* Make sure the power stays on for the rest of this function */
777 err = _mali_osk_pm_dev_ref_add();
778 if (_MALI_OSK_ERR_OK != err) goto pm_always_on_failed;
780 /* Detect which Mali GPU we are dealing with */
781 err = mali_parse_product_info();
782 if (_MALI_OSK_ERR_OK != err) goto product_info_parsing_failed;
784 /* The global_product_id is now populated with the correct Mali GPU */
786 /* Initialize MMU module */
787 err = mali_mmu_initialize();
788 if (_MALI_OSK_ERR_OK != err) goto mmu_init_failed;
790 if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
792 err = mali_dlbu_initialize();
793 if (_MALI_OSK_ERR_OK != err) goto dlbu_init_failed;
796 /* Start configuring the actual Mali hardware. */
797 err = mali_parse_config_l2_cache();
798 if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed;
799 err = mali_parse_config_groups();
800 if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed;
802 /* Initialize the schedulers */
803 err = mali_scheduler_initialize();
804 if (_MALI_OSK_ERR_OK != err) goto scheduler_init_failed;
805 err = mali_gp_scheduler_initialize();
806 if (_MALI_OSK_ERR_OK != err) goto gp_scheduler_init_failed;
807 err = mali_pp_scheduler_initialize();
808 if (_MALI_OSK_ERR_OK != err) goto pp_scheduler_init_failed;
810 /* Initialize the GPU utilization tracking */
811 err = mali_utilization_init();
812 if (_MALI_OSK_ERR_OK != err) goto utilization_init_failed;
814 /* Allowing the system to be turned off */
815 _mali_osk_pm_dev_ref_dec();
817 MALI_SUCCESS; /* all ok */
821 utilization_init_failed:
822 mali_pp_scheduler_terminate();
823 pp_scheduler_init_failed:
824 mali_gp_scheduler_terminate();
825 gp_scheduler_init_failed:
826 mali_scheduler_terminate();
827 scheduler_init_failed:
828 config_parsing_failed:
829 mali_delete_l2_cache_cores(); /* Delete L2 cache cores even if config parsing failed. */
831 mali_dlbu_terminate();
833 mali_mmu_terminate();
834 /* Nothing to roll back */
835 product_info_parsing_failed:
836 /* Allowing the system to be turned off */
837 _mali_osk_pm_dev_ref_dec();
842 struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
845 mali_pmu_delete(pmu);
848 parse_pmu_config_failed:
849 /* undoing mali_parse_config_memory() is done by mali_memory_terminate() */
850 parse_memory_config_failed:
851 mali_memory_terminate();
853 #if defined(CONFIG_MALI400_PROFILING)
854 _mali_osk_profiling_term();
856 mali_session_terminate();
861 void mali_terminate_subsystems(void)
863 struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
865 MALI_DEBUG_PRINT(2, ("terminate_subsystems() called\n"));
867 /* shut down subsystems in reverse order from startup */
869 /* We need the GPU to be powered up for the terminate sequence */
870 _mali_osk_pm_dev_ref_add();
872 mali_utilization_term();
873 mali_pp_scheduler_terminate();
874 mali_gp_scheduler_terminate();
875 mali_scheduler_terminate();
876 mali_delete_l2_cache_cores();
877 if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
879 mali_dlbu_terminate();
881 mali_mmu_terminate();
884 mali_pmu_delete(pmu);
887 mali_memory_terminate();
888 #if defined(CONFIG_MALI400_PROFILING)
889 _mali_osk_profiling_term();
892 /* Allowing the system to be turned off */
893 _mali_osk_pm_dev_ref_dec();
895 mali_session_terminate();
898 _mali_product_id_t mali_kernel_core_get_product_id(void)
900 return global_product_id;
903 _mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args )
905 MALI_DEBUG_ASSERT_POINTER(args);
906 MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
908 /* check compatability */
909 if ( args->version == _MALI_UK_API_VERSION )
911 args->compatible = 1;
915 args->compatible = 0;
918 args->version = _MALI_UK_API_VERSION; /* report our version */
920 /* success regardless of being compatible or not */
924 _mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args )
926 _mali_osk_errcode_t err;
927 _mali_osk_notification_t * notification;
928 _mali_osk_notification_queue_t *queue;
931 MALI_DEBUG_ASSERT_POINTER(args);
932 MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
934 queue = ((struct mali_session_data *)args->ctx)->ioctl_queue;
936 /* if the queue does not exist we're currently shutting down */
939 MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n"));
940 args->type = _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS;
944 /* receive a notification, might sleep */
945 err = _mali_osk_notification_queue_receive(queue, ¬ification);
946 if (_MALI_OSK_ERR_OK != err)
948 MALI_ERROR(err); /* errcode returned, pass on to caller */
951 /* copy the buffer to the user */
952 args->type = (_mali_uk_notification_type)notification->notification_type;
953 _mali_osk_memcpy(&args->data, notification->result_buffer, notification->result_buffer_size);
955 /* finished with the notification */
956 _mali_osk_notification_delete( notification );
958 MALI_SUCCESS; /* all ok */
961 _mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args )
963 _mali_osk_notification_t * notification;
964 _mali_osk_notification_queue_t *queue;
967 MALI_DEBUG_ASSERT_POINTER(args);
968 MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
970 queue = ((struct mali_session_data *)args->ctx)->ioctl_queue;
972 /* if the queue does not exist we're currently shutting down */
975 MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n"));
979 notification = _mali_osk_notification_create(args->type, 0);
980 if (NULL == notification)
982 MALI_PRINT_ERROR( ("Failed to create notification object\n"));
983 return _MALI_OSK_ERR_NOMEM;
986 _mali_osk_notification_queue_send(queue, notification);
988 MALI_SUCCESS; /* all ok */
991 _mali_osk_errcode_t _mali_ukk_open(void **context)
993 struct mali_session_data *session;
995 /* allocated struct to track this session */
996 session = (struct mali_session_data *)_mali_osk_calloc(1, sizeof(struct mali_session_data));
997 MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_NOMEM);
999 MALI_DEBUG_PRINT(3, ("Session starting\n"));
1001 /* create a response queue for this session */
1002 session->ioctl_queue = _mali_osk_notification_queue_init();
1003 if (NULL == session->ioctl_queue)
1005 _mali_osk_free(session);
1006 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1009 session->page_directory = mali_mmu_pagedir_alloc();
1010 if (NULL == session->page_directory)
1012 _mali_osk_notification_queue_term(session->ioctl_queue);
1013 _mali_osk_free(session);
1014 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1017 if (_MALI_OSK_ERR_OK != mali_mmu_pagedir_map(session->page_directory, MALI_DLBU_VIRT_ADDR, _MALI_OSK_MALI_PAGE_SIZE))
1019 MALI_PRINT_ERROR(("Failed to map DLBU page into session\n"));
1020 _mali_osk_notification_queue_term(session->ioctl_queue);
1021 _mali_osk_free(session);
1022 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1025 if (0 != mali_dlbu_phys_addr)
1027 mali_mmu_pagedir_update(session->page_directory, MALI_DLBU_VIRT_ADDR, mali_dlbu_phys_addr,
1028 _MALI_OSK_MALI_PAGE_SIZE, MALI_CACHE_STANDARD);
1031 if (_MALI_OSK_ERR_OK != mali_memory_session_begin(session))
1033 mali_mmu_pagedir_free(session->page_directory);
1034 _mali_osk_notification_queue_term(session->ioctl_queue);
1035 _mali_osk_free(session);
1036 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1041 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
1042 _mali_osk_list_init(&session->pending_jobs);
1043 session->pending_jobs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK,
1044 0, _MALI_OSK_LOCK_ORDER_SESSION_PENDING_JOBS);
1045 if (NULL == session->pending_jobs_lock)
1047 MALI_PRINT_ERROR(("Failed to create pending jobs lock\n"));
1048 mali_memory_session_end(session);
1049 mali_mmu_pagedir_free(session->page_directory);
1050 _mali_osk_notification_queue_term(session->ioctl_queue);
1051 _mali_osk_free(session);
1052 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1057 *context = (void*)session;
1059 /* Add session to the list of all sessions. */
1060 mali_session_add(session);
1062 /* Initialize list of jobs on this session */
1063 _MALI_OSK_INIT_LIST_HEAD(&session->job_list);
1065 MALI_DEBUG_PRINT(2, ("Session started\n"));
1069 _mali_osk_errcode_t _mali_ukk_close(void **context)
1071 struct mali_session_data *session;
1072 MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS);
1073 session = (struct mali_session_data *)*context;
1075 MALI_DEBUG_PRINT(3, ("Session ending\n"));
1077 /* Remove session from list of all sessions. */
1078 mali_session_remove(session);
1080 /* Abort pending jobs */
1083 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
1085 _mali_osk_list_t tmp_job_list;
1086 struct mali_pp_job *job, *tmp;
1087 _MALI_OSK_INIT_LIST_HEAD(&tmp_job_list);
1089 _mali_osk_lock_wait(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW);
1090 /* Abort asynchronous wait on fence. */
1091 _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &session->pending_jobs, struct mali_pp_job, list)
1093 MALI_DEBUG_PRINT(2, ("Sync: Aborting wait for session %x job %x\n", session, job));
1094 if (sync_fence_cancel_async(job->pre_fence, &job->sync_waiter))
1096 MALI_DEBUG_PRINT(2, ("Sync: Failed to abort job %x\n", job));
1098 _mali_osk_list_add(&job->list, &tmp_job_list);
1100 _mali_osk_lock_signal(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW);
1102 _mali_osk_wq_flush();
1104 _mali_osk_lock_term(session->pending_jobs_lock);
1107 _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &tmp_job_list, struct mali_pp_job, list)
1109 mali_pp_job_delete(job);
1115 /* Abort queued and running jobs */
1116 mali_gp_scheduler_abort_session(session);
1117 mali_pp_scheduler_abort_session(session);
1119 /* Flush pending work.
1120 * Needed to make sure all bottom half processing related to this
1121 * session has been completed, before we free internal data structures.
1123 _mali_osk_wq_flush();
1125 /* Free remaining memory allocated to this session */
1126 mali_memory_session_end(session);
1128 /* Free session data structures */
1129 mali_mmu_pagedir_free(session->page_directory);
1130 _mali_osk_notification_queue_term(session->ioctl_queue);
1131 _mali_osk_free(session);
1135 MALI_DEBUG_PRINT(2, ("Session has ended\n"));
1140 #if MALI_STATE_TRACKING
1141 u32 _mali_kernel_core_dump_state(char* buf, u32 size)
1143 int n = 0; /* Number of bytes written to buf */
1145 n += mali_gp_scheduler_dump_state(buf + n, size - n);
1146 n += mali_pp_scheduler_dump_state(buf + n, size - n);