2 * Copyright (C) 2010-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_pp_job.h"
28 #include "mali_group.h"
31 #include "mali_scheduler.h"
32 #include "mali_kernel_utilization.h"
33 #include "mali_l2_cache.h"
35 #include "mali_timeline.h"
36 #include "mali_soft_job.h"
37 #include "mali_pm_domain.h"
38 #if defined(CONFIG_MALI400_PROFILING)
39 #include "mali_osk_profiling.h"
41 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
42 #include "mali_profiling_internal.h"
46 /* Mali GPU memory. Real values come from module parameter or from device specific data */
47 unsigned int mali_dedicated_mem_start = 0;
48 unsigned int mali_dedicated_mem_size = 0;
49 unsigned int mali_shared_mem_size = 0;
51 /* Frame buffer memory to be accessible by Mali GPU */
52 int mali_fb_start = 0;
55 /* Mali max job runtime */
56 extern int mali_max_job_runtime;
58 /** Start profiling from module load? */
59 int mali_boot_profiling = 0;
61 /** Limits for the number of PP cores behind each L2 cache. */
62 int mali_max_pp_cores_group_1 = 0xFF;
63 int mali_max_pp_cores_group_2 = 0xFF;
65 int mali_inited_pp_cores_group_1 = 0;
66 int mali_inited_pp_cores_group_2 = 0;
68 static _mali_product_id_t global_product_id = _MALI_PRODUCT_ID_UNKNOWN;
69 static u32 global_gpu_base_address = 0;
70 static u32 global_gpu_major_version = 0;
71 static u32 global_gpu_minor_version = 0;
73 mali_bool mali_gpu_class_is_mali450 = MALI_FALSE;
75 static _mali_osk_errcode_t mali_set_global_gpu_base_address(void)
77 global_gpu_base_address = _mali_osk_resource_base_address();
78 if (0 == global_gpu_base_address) {
79 return _MALI_OSK_ERR_ITEM_NOT_FOUND;
82 return _MALI_OSK_ERR_OK;
85 static u32 mali_get_bcast_id(_mali_osk_resource_t *resource_pp)
87 switch (resource_pp->base - global_gpu_base_address) {
89 case 0x20000: /* fall-through for aliased mapping */
92 case 0x22000: /* fall-through for aliased mapping */
95 case 0x24000: /* fall-through for aliased mapping */
98 case 0x26000: /* fall-through for aliased mapping */
113 static _mali_osk_errcode_t mali_parse_product_info(void)
116 * Mali-200 has the PP core first, while Mali-300, Mali-400 and Mali-450 have the GP core first.
117 * Look at the version register for the first PP core in order to determine the GPU HW revision.
121 _mali_osk_resource_t first_pp_resource;
123 /* Find out where the first PP core is located */
124 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x8000, NULL)) {
125 /* Mali-300/400/450 */
126 first_pp_offset = 0x8000;
129 first_pp_offset = 0x0000;
132 /* Find the first PP core resource (again) */
133 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + first_pp_offset, &first_pp_resource)) {
134 /* Create a dummy PP object for this core so that we can read the version register */
135 struct mali_group *group = mali_group_create(NULL, NULL, NULL);
137 struct mali_pp_core *pp_core = mali_pp_create(&first_pp_resource, group, MALI_FALSE, mali_get_bcast_id(&first_pp_resource));
138 if (NULL != pp_core) {
139 u32 pp_version = mali_pp_core_get_version(pp_core);
140 mali_group_delete(group);
142 global_gpu_major_version = (pp_version >> 8) & 0xFF;
143 global_gpu_minor_version = pp_version & 0xFF;
145 switch (pp_version >> 16) {
146 case MALI200_PP_PRODUCT_ID:
147 global_product_id = _MALI_PRODUCT_ID_MALI200;
148 MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-200 r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
149 MALI_PRINT_ERROR(("Mali-200 is not supported by this driver.\n"));
152 case MALI300_PP_PRODUCT_ID:
153 global_product_id = _MALI_PRODUCT_ID_MALI300;
154 MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-300 r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
156 case MALI400_PP_PRODUCT_ID:
157 global_product_id = _MALI_PRODUCT_ID_MALI400;
158 MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-400 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
160 case MALI450_PP_PRODUCT_ID:
161 global_product_id = _MALI_PRODUCT_ID_MALI450;
162 MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-450 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
165 MALI_DEBUG_PRINT(2, ("Found unknown Mali GPU (r%up%u)\n", global_gpu_major_version, global_gpu_minor_version));
166 return _MALI_OSK_ERR_FAULT;
169 return _MALI_OSK_ERR_OK;
171 MALI_PRINT_ERROR(("Failed to create initial PP object\n"));
174 MALI_PRINT_ERROR(("Failed to create initial group object\n"));
177 MALI_PRINT_ERROR(("First PP core not specified in config file\n"));
180 return _MALI_OSK_ERR_FAULT;
184 static void mali_resource_count(u32 *pp_count, u32 *l2_count)
189 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x08000, NULL)) {
192 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0A000, NULL)) {
195 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0C000, NULL)) {
198 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0E000, NULL)) {
201 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x28000, NULL)) {
204 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2A000, NULL)) {
207 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2C000, NULL)) {
210 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2E000, NULL)) {
214 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, NULL)) {
217 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, NULL)) {
220 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, NULL)) {
225 static void mali_delete_groups(void)
227 struct mali_group *group;
229 group = mali_group_get_glob_group(0);
230 while (NULL != group) {
231 mali_group_delete(group);
232 group = mali_group_get_glob_group(0);
235 MALI_DEBUG_ASSERT(0 == mali_group_get_glob_num_groups());
238 static void mali_delete_l2_cache_cores(void)
240 struct mali_l2_cache_core *l2;
242 l2 = mali_l2_cache_core_get_glob_l2_core(0);
244 mali_l2_cache_delete(l2);
245 l2 = mali_l2_cache_core_get_glob_l2_core(0);
248 MALI_DEBUG_ASSERT(0 == mali_l2_cache_core_get_glob_num_l2_cores());
251 static struct mali_l2_cache_core *mali_create_l2_cache_core(_mali_osk_resource_t *resource)
253 struct mali_l2_cache_core *l2_cache = NULL;
255 if (NULL != resource) {
257 MALI_DEBUG_PRINT(3, ("Found L2 cache %s\n", resource->description));
259 l2_cache = mali_l2_cache_create(resource);
260 if (NULL == l2_cache) {
261 MALI_PRINT_ERROR(("Failed to create L2 cache object\n"));
265 MALI_DEBUG_PRINT(3, ("Created L2 cache core object\n"));
270 static _mali_osk_errcode_t mali_parse_config_l2_cache(void)
272 struct mali_l2_cache_core *l2_cache = NULL;
274 if (mali_is_mali400()) {
275 _mali_osk_resource_t l2_resource;
276 if (_MALI_OSK_ERR_OK != _mali_osk_resource_find(global_gpu_base_address + 0x1000, &l2_resource)) {
277 MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache in config file\n"));
278 return _MALI_OSK_ERR_FAULT;
281 l2_cache = mali_create_l2_cache_core(&l2_resource);
282 if (NULL == l2_cache) {
283 return _MALI_OSK_ERR_FAULT;
285 mali_pm_domain_add_l2(mali_pmu_get_domain_mask(MALI_L20_DOMAIN_INDEX), l2_cache);
286 } else if (mali_is_mali450()) {
288 * L2 for GP at 0x10000
289 * L2 for PP0-3 at 0x01000
290 * L2 for PP4-7 at 0x11000 (optional)
293 _mali_osk_resource_t l2_gp_resource;
294 _mali_osk_resource_t l2_pp_grp0_resource;
295 _mali_osk_resource_t l2_pp_grp1_resource;
297 /* Make cluster for GP's L2 */
298 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, &l2_gp_resource)) {
299 MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for GP\n"));
300 l2_cache = mali_create_l2_cache_core(&l2_gp_resource);
301 if (NULL == l2_cache) {
302 return _MALI_OSK_ERR_FAULT;
304 mali_pm_domain_add_l2(mali_pmu_get_domain_mask(MALI_L20_DOMAIN_INDEX), l2_cache);
306 MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for GP in config file\n"));
307 return _MALI_OSK_ERR_FAULT;
310 /* Find corresponding l2 domain */
311 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, &l2_pp_grp0_resource)) {
312 MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 0\n"));
313 l2_cache = mali_create_l2_cache_core(&l2_pp_grp0_resource);
314 if (NULL == l2_cache) {
315 return _MALI_OSK_ERR_FAULT;
317 mali_pm_domain_add_l2(mali_pmu_get_domain_mask(MALI_L21_DOMAIN_INDEX), l2_cache);
319 MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for PP group 0 in config file\n"));
320 return _MALI_OSK_ERR_FAULT;
323 /* Second PP core group is optional, don't fail if we don't find it */
324 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, &l2_pp_grp1_resource)) {
325 MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 1\n"));
326 l2_cache = mali_create_l2_cache_core(&l2_pp_grp1_resource);
327 if (NULL == l2_cache) {
328 return _MALI_OSK_ERR_FAULT;
330 mali_pm_domain_add_l2(mali_pmu_get_domain_mask(MALI_L22_DOMAIN_INDEX), l2_cache);
334 return _MALI_OSK_ERR_OK;
337 static struct mali_group *mali_create_group(struct mali_l2_cache_core *cache,
338 _mali_osk_resource_t *resource_mmu,
339 _mali_osk_resource_t *resource_gp,
340 _mali_osk_resource_t *resource_pp)
342 struct mali_mmu_core *mmu;
343 struct mali_group *group;
345 MALI_DEBUG_PRINT(3, ("Starting new group for MMU %s\n", resource_mmu->description));
347 /* Create the group object */
348 group = mali_group_create(cache, NULL, NULL);
350 MALI_PRINT_ERROR(("Failed to create group object for MMU %s\n", resource_mmu->description));
354 /* Create the MMU object inside group */
355 mmu = mali_mmu_create(resource_mmu, group, MALI_FALSE);
357 MALI_PRINT_ERROR(("Failed to create MMU object\n"));
358 mali_group_delete(group);
362 if (NULL != resource_gp) {
363 /* Create the GP core object inside this group */
364 struct mali_gp_core *gp_core = mali_gp_create(resource_gp, group);
365 if (NULL == gp_core) {
366 /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
367 MALI_PRINT_ERROR(("Failed to create GP object\n"));
368 mali_group_delete(group);
373 if (NULL != resource_pp) {
374 struct mali_pp_core *pp_core;
376 /* Create the PP core object inside this group */
377 pp_core = mali_pp_create(resource_pp, group, MALI_FALSE, mali_get_bcast_id(resource_pp));
378 if (NULL == pp_core) {
379 /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
380 MALI_PRINT_ERROR(("Failed to create PP object\n"));
381 mali_group_delete(group);
387 mali_group_lock(group);
388 mali_group_reset(group);
389 mali_group_unlock(group);
394 static _mali_osk_errcode_t mali_create_virtual_group(_mali_osk_resource_t *resource_mmu_pp_bcast,
395 _mali_osk_resource_t *resource_pp_bcast,
396 _mali_osk_resource_t *resource_dlbu,
397 _mali_osk_resource_t *resource_bcast)
399 struct mali_mmu_core *mmu_pp_bcast_core;
400 struct mali_pp_core *pp_bcast_core;
401 struct mali_dlbu_core *dlbu_core;
402 struct mali_bcast_unit *bcast_core;
403 struct mali_group *group;
405 MALI_DEBUG_PRINT(2, ("Starting new virtual group for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description));
407 /* Create the DLBU core object */
408 dlbu_core = mali_dlbu_create(resource_dlbu);
409 if (NULL == dlbu_core) {
410 MALI_PRINT_ERROR(("Failed to create DLBU object \n"));
411 return _MALI_OSK_ERR_FAULT;
414 /* Create the Broadcast unit core */
415 bcast_core = mali_bcast_unit_create(resource_bcast);
416 if (NULL == bcast_core) {
417 MALI_PRINT_ERROR(("Failed to create Broadcast unit object!\n"));
418 mali_dlbu_delete(dlbu_core);
419 return _MALI_OSK_ERR_FAULT;
422 /* Create the group object */
423 group = mali_group_create(NULL, dlbu_core, bcast_core);
425 MALI_PRINT_ERROR(("Failed to create group object for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description));
426 mali_bcast_unit_delete(bcast_core);
427 mali_dlbu_delete(dlbu_core);
428 return _MALI_OSK_ERR_FAULT;
431 /* Create the MMU object inside group */
432 mmu_pp_bcast_core = mali_mmu_create(resource_mmu_pp_bcast, group, MALI_TRUE);
433 if (NULL == mmu_pp_bcast_core) {
434 MALI_PRINT_ERROR(("Failed to create MMU PP broadcast object\n"));
435 mali_group_delete(group);
436 return _MALI_OSK_ERR_FAULT;
439 /* Create the PP core object inside this group */
440 pp_bcast_core = mali_pp_create(resource_pp_bcast, group, MALI_TRUE, 0);
441 if (NULL == pp_bcast_core) {
442 /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
443 MALI_PRINT_ERROR(("Failed to create PP object\n"));
444 mali_group_delete(group);
445 return _MALI_OSK_ERR_FAULT;
448 return _MALI_OSK_ERR_OK;
451 static _mali_osk_errcode_t mali_parse_config_groups(void)
453 struct mali_group *group;
454 int cluster_id_gp = 0;
455 int cluster_id_pp_grp0 = 0;
456 int cluster_id_pp_grp1 = 0;
459 _mali_osk_resource_t resource_gp;
460 _mali_osk_resource_t resource_gp_mmu;
461 _mali_osk_resource_t resource_pp[8];
462 _mali_osk_resource_t resource_pp_mmu[8];
463 _mali_osk_resource_t resource_pp_mmu_bcast;
464 _mali_osk_resource_t resource_pp_bcast;
465 _mali_osk_resource_t resource_dlbu;
466 _mali_osk_resource_t resource_bcast;
467 _mali_osk_errcode_t resource_gp_found;
468 _mali_osk_errcode_t resource_gp_mmu_found;
469 _mali_osk_errcode_t resource_pp_found[8];
470 _mali_osk_errcode_t resource_pp_mmu_found[8];
471 _mali_osk_errcode_t resource_pp_mmu_bcast_found;
472 _mali_osk_errcode_t resource_pp_bcast_found;
473 _mali_osk_errcode_t resource_dlbu_found;
474 _mali_osk_errcode_t resource_bcast_found;
476 if (!(mali_is_mali400() || mali_is_mali450())) {
477 /* No known HW core */
478 return _MALI_OSK_ERR_FAULT;
481 if (MALI_MAX_JOB_RUNTIME_DEFAULT == mali_max_job_runtime) {
482 /* Group settings are not overridden by module parameters, so use device settings */
483 struct _mali_osk_device_data data = { 0, };
485 if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
486 /* Use device specific settings (if defined) */
487 if (0 != data.max_job_runtime) {
488 mali_max_job_runtime = data.max_job_runtime;
493 if (mali_is_mali450()) {
494 /* Mali-450 have separate L2s for GP, and PP core group(s) */
495 cluster_id_pp_grp0 = 1;
496 cluster_id_pp_grp1 = 2;
499 resource_gp_found = _mali_osk_resource_find(global_gpu_base_address + 0x00000, &resource_gp);
500 resource_gp_mmu_found = _mali_osk_resource_find(global_gpu_base_address + 0x03000, &resource_gp_mmu);
501 resource_pp_found[0] = _mali_osk_resource_find(global_gpu_base_address + 0x08000, &(resource_pp[0]));
502 resource_pp_found[1] = _mali_osk_resource_find(global_gpu_base_address + 0x0A000, &(resource_pp[1]));
503 resource_pp_found[2] = _mali_osk_resource_find(global_gpu_base_address + 0x0C000, &(resource_pp[2]));
504 resource_pp_found[3] = _mali_osk_resource_find(global_gpu_base_address + 0x0E000, &(resource_pp[3]));
505 resource_pp_found[4] = _mali_osk_resource_find(global_gpu_base_address + 0x28000, &(resource_pp[4]));
506 resource_pp_found[5] = _mali_osk_resource_find(global_gpu_base_address + 0x2A000, &(resource_pp[5]));
507 resource_pp_found[6] = _mali_osk_resource_find(global_gpu_base_address + 0x2C000, &(resource_pp[6]));
508 resource_pp_found[7] = _mali_osk_resource_find(global_gpu_base_address + 0x2E000, &(resource_pp[7]));
509 resource_pp_mmu_found[0] = _mali_osk_resource_find(global_gpu_base_address + 0x04000, &(resource_pp_mmu[0]));
510 resource_pp_mmu_found[1] = _mali_osk_resource_find(global_gpu_base_address + 0x05000, &(resource_pp_mmu[1]));
511 resource_pp_mmu_found[2] = _mali_osk_resource_find(global_gpu_base_address + 0x06000, &(resource_pp_mmu[2]));
512 resource_pp_mmu_found[3] = _mali_osk_resource_find(global_gpu_base_address + 0x07000, &(resource_pp_mmu[3]));
513 resource_pp_mmu_found[4] = _mali_osk_resource_find(global_gpu_base_address + 0x1C000, &(resource_pp_mmu[4]));
514 resource_pp_mmu_found[5] = _mali_osk_resource_find(global_gpu_base_address + 0x1D000, &(resource_pp_mmu[5]));
515 resource_pp_mmu_found[6] = _mali_osk_resource_find(global_gpu_base_address + 0x1E000, &(resource_pp_mmu[6]));
516 resource_pp_mmu_found[7] = _mali_osk_resource_find(global_gpu_base_address + 0x1F000, &(resource_pp_mmu[7]));
519 if (mali_is_mali450()) {
520 resource_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x13000, &resource_bcast);
521 resource_dlbu_found = _mali_osk_resource_find(global_gpu_base_address + 0x14000, &resource_dlbu);
522 resource_pp_mmu_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x15000, &resource_pp_mmu_bcast);
523 resource_pp_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x16000, &resource_pp_bcast);
525 if (_MALI_OSK_ERR_OK != resource_bcast_found ||
526 _MALI_OSK_ERR_OK != resource_dlbu_found ||
527 _MALI_OSK_ERR_OK != resource_pp_mmu_bcast_found ||
528 _MALI_OSK_ERR_OK != resource_pp_bcast_found) {
529 /* Missing mandatory core(s) for Mali-450 */
530 MALI_DEBUG_PRINT(2, ("Missing mandatory resources, Mali-450 needs DLBU, Broadcast unit, virtual PP core and virtual MMU\n"));
531 return _MALI_OSK_ERR_FAULT;
535 if (_MALI_OSK_ERR_OK != resource_gp_found ||
536 _MALI_OSK_ERR_OK != resource_gp_mmu_found ||
537 _MALI_OSK_ERR_OK != resource_pp_found[0] ||
538 _MALI_OSK_ERR_OK != resource_pp_mmu_found[0]) {
539 /* Missing mandatory core(s) */
540 MALI_DEBUG_PRINT(2, ("Missing mandatory resource, need at least one GP and one PP, both with a separate MMU\n"));
541 return _MALI_OSK_ERR_FAULT;
544 MALI_DEBUG_ASSERT(1 <= mali_l2_cache_core_get_glob_num_l2_cores());
545 group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_gp), &resource_gp_mmu, &resource_gp, NULL);
547 return _MALI_OSK_ERR_FAULT;
550 /* Add GP in group, for PMU ref count */
551 mali_pm_domain_add_group(mali_pmu_get_domain_mask(MALI_GP_DOMAIN_INDEX), group);
553 /* Create group for first (and mandatory) PP core */
554 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 */
555 group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[0], NULL, &resource_pp[0]);
557 return _MALI_OSK_ERR_FAULT;
560 /* Find corresponding pp domain */
561 mali_pm_domain_add_group(mali_pmu_get_domain_mask(MALI_PP0_DOMAIN_INDEX), group);
563 mali_inited_pp_cores_group_1++;
565 /* Create groups for rest of the cores in the first PP core group */
566 for (i = 1; i < 4; i++) { /* First half of the PP cores belong to first core group */
567 if (mali_inited_pp_cores_group_1 < mali_max_pp_cores_group_1) {
568 if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[i]) {
569 group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[i], NULL, &resource_pp[i]);
571 return _MALI_OSK_ERR_FAULT;
574 mali_pm_domain_add_group(mali_pmu_get_domain_mask(i + MALI_PP0_DOMAIN_INDEX), group);
576 mali_inited_pp_cores_group_1++;
581 /* Create groups for cores in the second PP core group */
582 for (i = 4; i < 8; i++) { /* Second half of the PP cores belong to second core group */
583 if (mali_inited_pp_cores_group_2 < mali_max_pp_cores_group_2) {
584 if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[i]) {
585 MALI_DEBUG_ASSERT(mali_l2_cache_core_get_glob_num_l2_cores() >= 2); /* Only Mali-450 have a second core group */
586 group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp1), &resource_pp_mmu[i], NULL, &resource_pp[i]);
588 return _MALI_OSK_ERR_FAULT;
590 mali_pm_domain_add_group(mali_pmu_get_domain_mask(i + MALI_PP0_DOMAIN_INDEX), group);
591 mali_inited_pp_cores_group_2++;
596 if(mali_is_mali450()) {
597 _mali_osk_errcode_t err = mali_create_virtual_group(&resource_pp_mmu_bcast, &resource_pp_bcast, &resource_dlbu, &resource_bcast);
598 if (_MALI_OSK_ERR_OK != err) {
603 mali_max_pp_cores_group_1 = mali_inited_pp_cores_group_1;
604 mali_max_pp_cores_group_2 = mali_inited_pp_cores_group_2;
605 MALI_DEBUG_PRINT(2, ("%d+%d PP cores initialized\n", mali_inited_pp_cores_group_1, mali_inited_pp_cores_group_2));
607 return _MALI_OSK_ERR_OK;
610 static _mali_osk_errcode_t mali_check_shared_interrupts(void)
612 #if !defined(CONFIG_MALI_SHARED_INTERRUPTS)
613 if (MALI_TRUE == _mali_osk_shared_interrupts()) {
614 MALI_PRINT_ERROR(("Shared interrupts detected, but driver support is not enabled\n"));
615 return _MALI_OSK_ERR_FAULT;
617 #endif /* !defined(CONFIG_MALI_SHARED_INTERRUPTS) */
619 /* It is OK to compile support for shared interrupts even if Mali is not using it. */
620 return _MALI_OSK_ERR_OK;
623 static _mali_osk_errcode_t mali_create_pm_domains(void)
627 for (i = 0; i < MALI_MAX_NUMBER_OF_DOMAINS; i++) {
628 if (0x0 == mali_pmu_get_domain_mask(i)) continue;
630 if (NULL == mali_pm_domain_create(mali_pmu_get_domain_mask(i))) {
631 return _MALI_OSK_ERR_NOMEM;
635 return _MALI_OSK_ERR_OK;
638 static void mali_use_default_pm_domain_config(void)
640 u32 pp_count_gr1 = 0;
641 u32 pp_count_gr2 = 0;
644 MALI_DEBUG_ASSERT(0 != global_gpu_base_address);
647 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x00000, NULL)) {
648 mali_pmu_set_domain_mask(MALI_GP_DOMAIN_INDEX, 0x01);
652 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x08000, NULL)) {
655 if (mali_is_mali400()) {
656 mali_pmu_set_domain_mask(MALI_PP0_DOMAIN_INDEX, 0x01<<2);
657 } else if (mali_is_mali450()) {
658 mali_pmu_set_domain_mask(MALI_PP0_DOMAIN_INDEX, 0x01<<1);
662 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0A000, NULL)) {
665 if (mali_is_mali400()) {
666 mali_pmu_set_domain_mask(MALI_PP1_DOMAIN_INDEX, 0x01<<3);
667 } else if (mali_is_mali450()) {
668 mali_pmu_set_domain_mask(MALI_PP1_DOMAIN_INDEX, 0x01<<2);
672 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0C000, NULL)) {
675 if (mali_is_mali400()) {
676 mali_pmu_set_domain_mask(MALI_PP2_DOMAIN_INDEX, 0x01<<4);
677 } else if (mali_is_mali450()) {
678 mali_pmu_set_domain_mask(MALI_PP2_DOMAIN_INDEX, 0x01<<2);
682 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0E000, NULL)) {
685 if (mali_is_mali400()) {
686 mali_pmu_set_domain_mask(MALI_PP3_DOMAIN_INDEX, 0x01<<5);
687 } else if (mali_is_mali450()) {
688 mali_pmu_set_domain_mask(MALI_PP3_DOMAIN_INDEX, 0x01<<2);
693 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x28000, NULL)) {
696 mali_pmu_set_domain_mask(MALI_PP4_DOMAIN_INDEX, 0x01<<3);
699 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2A000, NULL)) {
702 mali_pmu_set_domain_mask(MALI_PP5_DOMAIN_INDEX, 0x01<<3);
705 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2C000, NULL)) {
708 mali_pmu_set_domain_mask(MALI_PP6_DOMAIN_INDEX, 0x01<<3);
711 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2E000, NULL)) {
714 mali_pmu_set_domain_mask(MALI_PP7_DOMAIN_INDEX, 0x01<<3);
717 /* L2gp/L2PP0/L2PP4 */
718 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, NULL)) {
721 if (mali_is_mali400()) {
722 mali_pmu_set_domain_mask(MALI_L20_DOMAIN_INDEX, 0x01<<1);
723 } else if (mali_is_mali450()) {
724 mali_pmu_set_domain_mask(MALI_L20_DOMAIN_INDEX, 0x01<<0);
728 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, NULL)) {
731 mali_pmu_set_domain_mask(MALI_L21_DOMAIN_INDEX, 0x01<<1);
734 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, NULL)) {
737 mali_pmu_set_domain_mask(MALI_L22_DOMAIN_INDEX, 0x01<<3);
740 MALI_DEBUG_PRINT(2, ("Using default PMU domain config: (%d) gr1_pp_cores, (%d) gr2_pp_cores, (%d) l2_count. \n", pp_count_gr1, pp_count_gr2, l2_count));
743 static void mali_set_pmu_global_domain_config(void)
745 struct _mali_osk_device_data data = { 0, };
748 if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
749 /* Check whether has customized pmu domain configure */
750 for (i = 0; i < MALI_MAX_NUMBER_OF_DOMAINS; i++) {
751 if (0 != data.pmu_domain_config[i]) break;
754 if (MALI_MAX_NUMBER_OF_DOMAINS == i) {
755 mali_use_default_pm_domain_config();
757 /* Copy the customer config to global config */
758 mali_pmu_copy_domain_mask(data.pmu_domain_config, sizeof(data.pmu_domain_config));
763 static _mali_osk_errcode_t mali_parse_config_pmu(void)
765 _mali_osk_resource_t resource_pmu;
767 MALI_DEBUG_ASSERT(0 != global_gpu_base_address);
769 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x02000, &resource_pmu)) {
770 struct mali_pmu_core *pmu;
772 mali_set_pmu_global_domain_config();
774 pmu = mali_pmu_create(&resource_pmu);
776 MALI_PRINT_ERROR(("Failed to create PMU\n"));
777 return _MALI_OSK_ERR_FAULT;
781 /* It's ok if the PMU doesn't exist */
782 return _MALI_OSK_ERR_OK;
785 static _mali_osk_errcode_t mali_parse_config_dma(void)
787 _mali_osk_resource_t resource_dma;
789 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x12000, &resource_dma)) {
790 if (NULL == mali_dma_create(&resource_dma)) {
791 return _MALI_OSK_ERR_FAULT;
793 return _MALI_OSK_ERR_OK;
795 return _MALI_OSK_ERR_ITEM_NOT_FOUND;
799 static _mali_osk_errcode_t mali_parse_config_memory(void)
801 _mali_osk_errcode_t ret;
803 if (0 == mali_dedicated_mem_start && 0 == mali_dedicated_mem_size && 0 == mali_shared_mem_size) {
804 /* Memory settings are not overridden by module parameters, so use device settings */
805 struct _mali_osk_device_data data = { 0, };
807 if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
808 /* Use device specific settings (if defined) */
809 mali_dedicated_mem_start = data.dedicated_mem_start;
810 mali_dedicated_mem_size = data.dedicated_mem_size;
811 mali_shared_mem_size = data.shared_mem_size;
814 if (0 == mali_dedicated_mem_start && 0 == mali_dedicated_mem_size && 0 == mali_shared_mem_size) {
815 /* No GPU memory specified */
816 return _MALI_OSK_ERR_INVALID_ARGS;
819 MALI_DEBUG_PRINT(2, ("Using device defined memory settings (dedicated: 0x%08X@0x%08X, shared: 0x%08X)\n",
820 mali_dedicated_mem_size, mali_dedicated_mem_start, mali_shared_mem_size));
822 MALI_DEBUG_PRINT(2, ("Using module defined memory settings (dedicated: 0x%08X@0x%08X, shared: 0x%08X)\n",
823 mali_dedicated_mem_size, mali_dedicated_mem_start, mali_shared_mem_size));
826 if (0 < mali_dedicated_mem_size && 0 != mali_dedicated_mem_start) {
827 /* Dedicated memory */
828 ret = mali_memory_core_resource_dedicated_memory(mali_dedicated_mem_start, mali_dedicated_mem_size);
829 if (_MALI_OSK_ERR_OK != ret) {
830 MALI_PRINT_ERROR(("Failed to register dedicated memory\n"));
831 mali_memory_terminate();
836 if (0 < mali_shared_mem_size) {
837 /* Shared OS memory */
838 ret = mali_memory_core_resource_os_memory(mali_shared_mem_size);
839 if (_MALI_OSK_ERR_OK != ret) {
840 MALI_PRINT_ERROR(("Failed to register shared OS memory\n"));
841 mali_memory_terminate();
846 if (0 == mali_fb_start && 0 == mali_fb_size) {
847 /* Frame buffer settings are not overridden by module parameters, so use device settings */
848 struct _mali_osk_device_data data = { 0, };
850 if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
851 /* Use device specific settings (if defined) */
852 mali_fb_start = data.fb_start;
853 mali_fb_size = data.fb_size;
856 MALI_DEBUG_PRINT(2, ("Using device defined frame buffer settings (0x%08X@0x%08X)\n",
857 mali_fb_size, mali_fb_start));
859 MALI_DEBUG_PRINT(2, ("Using module defined frame buffer settings (0x%08X@0x%08X)\n",
860 mali_fb_size, mali_fb_start));
863 if (0 != mali_fb_size) {
864 /* Register frame buffer */
865 ret = mali_mem_validation_add_range(mali_fb_start, mali_fb_size);
866 if (_MALI_OSK_ERR_OK != ret) {
867 MALI_PRINT_ERROR(("Failed to register frame buffer memory region\n"));
868 mali_memory_terminate();
873 return _MALI_OSK_ERR_OK;
876 static void mali_detect_gpu_class(void)
878 u32 number_of_pp_cores = 0;
879 u32 number_of_l2_caches = 0;
881 mali_resource_count(&number_of_pp_cores, &number_of_l2_caches);
882 if (number_of_l2_caches > 1) {
883 mali_gpu_class_is_mali450 = MALI_TRUE;
887 _mali_osk_errcode_t mali_initialize_subsystems(void)
889 _mali_osk_errcode_t err;
890 struct mali_pmu_core *pmu;
892 mali_pp_job_initialize();
894 err = mali_session_initialize();
895 if (_MALI_OSK_ERR_OK != err) goto session_init_failed;
897 #if defined(CONFIG_MALI400_PROFILING)
898 err = _mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE);
899 if (_MALI_OSK_ERR_OK != err) {
900 /* No biggie if we weren't able to initialize the profiling */
901 MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n"));
905 err = mali_memory_initialize();
906 if (_MALI_OSK_ERR_OK != err) goto memory_init_failed;
908 /* Configure memory early. Memory allocation needed for mali_mmu_initialize. */
909 err = mali_parse_config_memory();
910 if (_MALI_OSK_ERR_OK != err) goto parse_memory_config_failed;
912 err = mali_set_global_gpu_base_address();
913 if (_MALI_OSK_ERR_OK != err) goto set_global_gpu_base_address_failed;
915 /* Detect gpu class according to l2 cache number */
916 mali_detect_gpu_class();
918 err = mali_check_shared_interrupts();
919 if (_MALI_OSK_ERR_OK != err) goto check_shared_interrupts_failed;
921 err = mali_pp_scheduler_initialize();
922 if (_MALI_OSK_ERR_OK != err) goto pp_scheduler_init_failed;
924 /* Initialize the power management module */
925 err = mali_pm_initialize();
926 if (_MALI_OSK_ERR_OK != err) goto pm_init_failed;
928 /* Initialize the MALI PMU */
929 err = mali_parse_config_pmu();
930 if (_MALI_OSK_ERR_OK != err) goto parse_pmu_config_failed;
932 /* Make sure the power stays on for the rest of this function */
933 err = _mali_osk_pm_dev_ref_add();
934 if (_MALI_OSK_ERR_OK != err) goto pm_always_on_failed;
937 * If run-time PM is used, then the mali_pm module has now already been
938 * notified that the power now is on (through the resume callback functions).
939 * However, if run-time PM is not used, then there will probably not be any
940 * calls to the resume callback functions, so we need to explicitly tell it
941 * that the power is on.
943 mali_pm_set_power_is_on();
945 /* Reset PMU HW and ensure all Mali power domains are on */
946 pmu = mali_pmu_get_global_pmu_core();
948 err = mali_pmu_reset(pmu);
949 if (_MALI_OSK_ERR_OK != err) goto pmu_reset_failed;
952 /* Detect which Mali GPU we are dealing with */
953 err = mali_parse_product_info();
954 if (_MALI_OSK_ERR_OK != err) goto product_info_parsing_failed;
956 /* The global_product_id is now populated with the correct Mali GPU */
958 /* Create PM domains only if PMU exists */
960 err = mali_create_pm_domains();
961 if (_MALI_OSK_ERR_OK != err) goto pm_domain_failed;
964 /* Initialize MMU module */
965 err = mali_mmu_initialize();
966 if (_MALI_OSK_ERR_OK != err) goto mmu_init_failed;
968 if (mali_is_mali450()) {
969 err = mali_dlbu_initialize();
970 if (_MALI_OSK_ERR_OK != err) goto dlbu_init_failed;
972 err = mali_parse_config_dma();
973 if (_MALI_OSK_ERR_OK != err) goto dma_parsing_failed;
976 /* Start configuring the actual Mali hardware. */
977 err = mali_parse_config_l2_cache();
978 if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed;
979 err = mali_parse_config_groups();
980 if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed;
982 /* Initialize the schedulers */
983 err = mali_scheduler_initialize();
984 if (_MALI_OSK_ERR_OK != err) goto scheduler_init_failed;
985 err = mali_gp_scheduler_initialize();
986 if (_MALI_OSK_ERR_OK != err) goto gp_scheduler_init_failed;
988 /* PP scheduler population can't fail */
989 mali_pp_scheduler_populate();
991 /* Initialize the GPU utilization tracking */
992 err = mali_utilization_init();
993 if (_MALI_OSK_ERR_OK != err) goto utilization_init_failed;
995 /* Allowing the system to be turned off */
996 _mali_osk_pm_dev_ref_dec();
998 MALI_SUCCESS; /* all ok */
1000 /* Error handling */
1002 utilization_init_failed:
1003 mali_pp_scheduler_depopulate();
1004 mali_gp_scheduler_terminate();
1005 gp_scheduler_init_failed:
1006 mali_scheduler_terminate();
1007 scheduler_init_failed:
1008 config_parsing_failed:
1009 mali_delete_groups(); /* Delete any groups not (yet) owned by a scheduler */
1010 mali_delete_l2_cache_cores(); /* Delete L2 cache cores even if config parsing failed. */
1012 struct mali_dma_core *dma = mali_dma_get_global_dma_core();
1013 if (NULL != dma) mali_dma_delete(dma);
1016 mali_dlbu_terminate();
1018 mali_mmu_terminate();
1020 mali_pm_domain_terminate();
1022 /* Nothing to roll back */
1023 product_info_parsing_failed:
1024 /* Nothing to roll back */
1026 /* Allowing the system to be turned off */
1027 _mali_osk_pm_dev_ref_dec();
1028 pm_always_on_failed:
1029 pmu = mali_pmu_get_global_pmu_core();
1031 mali_pmu_delete(pmu);
1033 parse_pmu_config_failed:
1034 mali_pm_terminate();
1036 mali_pp_scheduler_terminate();
1037 pp_scheduler_init_failed:
1038 check_shared_interrupts_failed:
1039 global_gpu_base_address = 0;
1040 set_global_gpu_base_address_failed:
1041 /* undoing mali_parse_config_memory() is done by mali_memory_terminate() */
1042 parse_memory_config_failed:
1043 mali_memory_terminate();
1045 #if defined(CONFIG_MALI400_PROFILING)
1046 _mali_osk_profiling_term();
1048 mali_session_terminate();
1049 session_init_failed:
1050 mali_pp_job_terminate();
1054 void mali_terminate_subsystems(void)
1056 struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
1057 struct mali_dma_core *dma = mali_dma_get_global_dma_core();
1059 MALI_DEBUG_PRINT(2, ("terminate_subsystems() called\n"));
1061 /* shut down subsystems in reverse order from startup */
1063 /* We need the GPU to be powered up for the terminate sequence */
1064 _mali_osk_pm_dev_ref_add();
1066 mali_utilization_term();
1067 mali_pp_scheduler_depopulate();
1068 mali_gp_scheduler_terminate();
1069 mali_scheduler_terminate();
1070 mali_delete_l2_cache_cores();
1071 if (mali_is_mali450()) {
1072 mali_dlbu_terminate();
1074 mali_mmu_terminate();
1076 mali_pmu_delete(pmu);
1079 mali_dma_delete(dma);
1081 mali_pm_terminate();
1082 mali_memory_terminate();
1083 #if defined(CONFIG_MALI400_PROFILING)
1084 _mali_osk_profiling_term();
1087 /* Allowing the system to be turned off */
1088 _mali_osk_pm_dev_ref_dec();
1090 mali_pp_scheduler_terminate();
1091 mali_session_terminate();
1093 mali_pp_job_terminate();
1096 _mali_product_id_t mali_kernel_core_get_product_id(void)
1098 return global_product_id;
1101 u32 mali_kernel_core_get_gpu_major_version(void)
1103 return global_gpu_major_version;
1106 u32 mali_kernel_core_get_gpu_minor_version(void)
1108 return global_gpu_minor_version;
1111 _mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args )
1113 MALI_DEBUG_ASSERT_POINTER(args);
1114 MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
1116 /* check compatability */
1117 if ( args->version == _MALI_UK_API_VERSION ) {
1118 args->compatible = 1;
1120 args->compatible = 0;
1123 args->version = _MALI_UK_API_VERSION; /* report our version */
1125 /* success regardless of being compatible or not */
1129 _mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args )
1131 _mali_osk_errcode_t err;
1132 _mali_osk_notification_t * notification;
1133 _mali_osk_notification_queue_t *queue;
1136 MALI_DEBUG_ASSERT_POINTER(args);
1137 MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
1139 queue = ((struct mali_session_data *)args->ctx)->ioctl_queue;
1141 /* if the queue does not exist we're currently shutting down */
1142 if (NULL == queue) {
1143 MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n"));
1144 args->type = _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS;
1148 /* receive a notification, might sleep */
1149 err = _mali_osk_notification_queue_receive(queue, ¬ification);
1150 if (_MALI_OSK_ERR_OK != err) {
1151 MALI_ERROR(err); /* errcode returned, pass on to caller */
1154 /* copy the buffer to the user */
1155 args->type = (_mali_uk_notification_type)notification->notification_type;
1156 _mali_osk_memcpy(&args->data, notification->result_buffer, notification->result_buffer_size);
1158 /* finished with the notification */
1159 _mali_osk_notification_delete( notification );
1161 MALI_SUCCESS; /* all ok */
1164 _mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args )
1166 _mali_osk_notification_t * notification;
1167 _mali_osk_notification_queue_t *queue;
1170 MALI_DEBUG_ASSERT_POINTER(args);
1171 MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
1173 queue = ((struct mali_session_data *)args->ctx)->ioctl_queue;
1175 /* if the queue does not exist we're currently shutting down */
1176 if (NULL == queue) {
1177 MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n"));
1181 notification = _mali_osk_notification_create(args->type, 0);
1182 if (NULL == notification) {
1183 MALI_PRINT_ERROR( ("Failed to create notification object\n"));
1184 return _MALI_OSK_ERR_NOMEM;
1187 _mali_osk_notification_queue_send(queue, notification);
1189 MALI_SUCCESS; /* all ok */
1192 _mali_osk_errcode_t _mali_ukk_request_high_priority( _mali_uk_request_high_priority_s *args )
1194 struct mali_session_data *session;
1196 MALI_DEBUG_ASSERT_POINTER(args);
1197 MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
1199 session = (struct mali_session_data *) args->ctx;
1201 if (!session->use_high_priority_job_queue) {
1202 session->use_high_priority_job_queue = MALI_TRUE;
1203 MALI_DEBUG_PRINT(2, ("Session 0x%08X with pid %d was granted higher priority.\n", session, _mali_osk_get_pid()));
1209 _mali_osk_errcode_t _mali_ukk_open(void **context)
1212 struct mali_session_data *session;
1214 /* allocated struct to track this session */
1215 session = (struct mali_session_data *)_mali_osk_calloc(1, sizeof(struct mali_session_data));
1216 MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_NOMEM);
1218 MALI_DEBUG_PRINT(3, ("Session starting\n"));
1220 /* create a response queue for this session */
1221 session->ioctl_queue = _mali_osk_notification_queue_init();
1222 if (NULL == session->ioctl_queue) {
1223 _mali_osk_free(session);
1224 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1227 session->page_directory = mali_mmu_pagedir_alloc();
1228 if (NULL == session->page_directory) {
1229 _mali_osk_notification_queue_term(session->ioctl_queue);
1230 _mali_osk_free(session);
1231 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1234 if (_MALI_OSK_ERR_OK != mali_mmu_pagedir_map(session->page_directory, MALI_DLBU_VIRT_ADDR, _MALI_OSK_MALI_PAGE_SIZE)) {
1235 MALI_PRINT_ERROR(("Failed to map DLBU page into session\n"));
1236 _mali_osk_notification_queue_term(session->ioctl_queue);
1237 _mali_osk_free(session);
1238 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1241 if (0 != mali_dlbu_phys_addr) {
1242 mali_mmu_pagedir_update(session->page_directory, MALI_DLBU_VIRT_ADDR, mali_dlbu_phys_addr,
1243 _MALI_OSK_MALI_PAGE_SIZE, MALI_MMU_FLAGS_DEFAULT);
1246 if (_MALI_OSK_ERR_OK != mali_memory_session_begin(session)) {
1247 mali_mmu_pagedir_free(session->page_directory);
1248 _mali_osk_notification_queue_term(session->ioctl_queue);
1249 _mali_osk_free(session);
1250 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1253 /* Create soft system. */
1254 session->soft_job_system = mali_soft_job_system_create(session);
1255 if (NULL == session->soft_job_system) {
1256 mali_memory_session_end(session);
1257 mali_mmu_pagedir_free(session->page_directory);
1258 _mali_osk_notification_queue_term(session->ioctl_queue);
1259 _mali_osk_free(session);
1260 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1263 /* Create timeline system. */
1264 session->timeline_system = mali_timeline_system_create(session);
1265 if (NULL == session->timeline_system) {
1266 mali_soft_job_system_destroy(session->soft_job_system);
1267 mali_memory_session_end(session);
1268 mali_mmu_pagedir_free(session->page_directory);
1269 _mali_osk_notification_queue_term(session->ioctl_queue);
1270 _mali_osk_free(session);
1271 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1274 #if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
1275 if ( _MALI_OSK_ERR_OK != _mali_osk_atomic_init(&session->number_of_window_jobs, 0)) {
1276 MALI_DEBUG_PRINT_ERROR(("Initialization of atomic number_of_window_jobs failed.\n"));
1277 mali_timeline_system_destroy(session->timeline_system);
1278 mali_soft_job_system_destroy(session->soft_job_system);
1279 mali_memory_session_end(session);
1280 mali_mmu_pagedir_free(session->page_directory);
1281 _mali_osk_notification_queue_term(session->ioctl_queue);
1282 _mali_osk_free(session);
1283 return _MALI_OSK_ERR_FAULT;
1287 session->use_high_priority_job_queue = MALI_FALSE;
1289 /* Initialize list of PP jobs on this session. */
1290 _MALI_OSK_INIT_LIST_HEAD(&session->pp_job_list);
1292 /* Initialize the pp_job_fb_lookup_list array used to quickly lookup jobs from a given frame builder */
1293 for (i = 0; i < MALI_PP_JOB_FB_LOOKUP_LIST_SIZE; ++i) {
1294 _MALI_OSK_INIT_LIST_HEAD(&session->pp_job_fb_lookup_list[i]);
1297 *context = (void*)session;
1299 /* Add session to the list of all sessions. */
1300 mali_session_add(session);
1302 MALI_DEBUG_PRINT(2, ("Session started\n"));
1306 _mali_osk_errcode_t _mali_ukk_close(void **context)
1308 struct mali_session_data *session;
1309 MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS);
1310 session = (struct mali_session_data *)*context;
1312 MALI_DEBUG_PRINT(3, ("Session ending\n"));
1314 MALI_DEBUG_ASSERT_POINTER(session->soft_job_system);
1315 MALI_DEBUG_ASSERT_POINTER(session->timeline_system);
1317 /* Remove session from list of all sessions. */
1318 mali_session_remove(session);
1320 /* This flag is used to prevent queueing of jobs due to activation. */
1321 session->is_aborting = MALI_TRUE;
1323 /* Stop the soft job timer. */
1324 mali_timeline_system_stop_timer(session->timeline_system);
1326 /* Abort queued and running GP and PP jobs. */
1327 mali_gp_scheduler_abort_session(session);
1328 mali_pp_scheduler_abort_session(session);
1330 /* Abort the soft job system. */
1331 mali_soft_job_system_abort(session->soft_job_system);
1333 /* Force execution of all pending bottom half processing for GP and PP. */
1334 _mali_osk_wq_flush();
1336 /* The session PP list should now be empty. */
1337 MALI_DEBUG_ASSERT(_mali_osk_list_empty(&session->pp_job_list));
1339 /* At this point the GP and PP scheduler no longer has any jobs queued or running from this
1340 * session, and all soft jobs in the soft job system has been destroyed. */
1342 /* Any trackers left in the timeline system are directly or indirectly waiting on external
1343 * sync fences. Cancel all sync fence waiters to trigger activation of all remaining
1344 * trackers. This call will sleep until all timelines are empty. */
1345 mali_timeline_system_abort(session->timeline_system);
1347 /* Flush pending work.
1348 * Needed to make sure all bottom half processing related to this
1349 * session has been completed, before we free internal data structures.
1351 _mali_osk_wq_flush();
1353 /* Destroy timeline system. */
1354 mali_timeline_system_destroy(session->timeline_system);
1355 session->timeline_system = NULL;
1357 /* Destroy soft system. */
1358 mali_soft_job_system_destroy(session->soft_job_system);
1359 session->soft_job_system = NULL;
1362 /* Check that the pp_job_fb_lookup_list array is empty. */
1364 for (i = 0; i < MALI_PP_JOB_FB_LOOKUP_LIST_SIZE; ++i)
1366 MALI_DEBUG_ASSERT(_mali_osk_list_empty(&session->pp_job_fb_lookup_list[i]));
1370 /* Free remaining memory allocated to this session */
1371 mali_memory_session_end(session);
1373 #if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
1374 _mali_osk_atomic_term(&session->number_of_window_jobs);
1377 /* Free session data structures */
1378 mali_mmu_pagedir_free(session->page_directory);
1379 _mali_osk_notification_queue_term(session->ioctl_queue);
1380 _mali_osk_free(session);
1384 MALI_DEBUG_PRINT(2, ("Session has ended\n"));
1389 #if MALI_STATE_TRACKING
1390 u32 _mali_kernel_core_dump_state(char* buf, u32 size)
1392 int n = 0; /* Number of bytes written to buf */
1394 n += mali_gp_scheduler_dump_state(buf + n, size - n);
1395 n += mali_pp_scheduler_dump_state(buf + n, size - n);