6dca53af2e4755005c7c49ab160f524be101d184
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / common / mali_kernel_core.c
1 /*
2  * Copyright (C) 2010-2015 ARM Limited. All rights reserved.
3  * 
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  * 
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
9  */
10
11 #include "mali_kernel_common.h"
12 #include "mali_session.h"
13 #include "mali_osk.h"
14 #include "mali_osk_mali.h"
15 #include "mali_ukk.h"
16 #include "mali_kernel_core.h"
17 #include "mali_memory.h"
18 #include "mali_mem_validation.h"
19 #include "mali_mmu.h"
20 #include "mali_mmu_page_directory.h"
21 #include "mali_dlbu.h"
22 #include "mali_broadcast.h"
23 #include "mali_gp.h"
24 #include "mali_pp.h"
25 #include "mali_executor.h"
26 #include "mali_pp_job.h"
27 #include "mali_group.h"
28 #include "mali_pm.h"
29 #include "mali_pmu.h"
30 #include "mali_scheduler.h"
31 #include "mali_kernel_utilization.h"
32 #include "mali_l2_cache.h"
33 #include "mali_timeline.h"
34 #include "mali_soft_job.h"
35 #include "mali_pm_domain.h"
36 #if defined(CONFIG_MALI400_PROFILING)
37 #include "mali_osk_profiling.h"
38 #endif
39 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
40 #include "mali_profiling_internal.h"
41 #endif
42 #include "mali_control_timer.h"
43 #include "mali_dvfs_policy.h"
44 #include <linux/sched.h>
45
46 #define MALI_SHARED_MEMORY_DEFAULT_SIZE 0xffffffff
47
48 /* Mali GPU memory. Real values come from module parameter or from device specific data */
49 unsigned int mali_dedicated_mem_start = 0;
50 unsigned int mali_dedicated_mem_size = 0;
51
52 /* Default shared memory size is set to 4G. */
53 unsigned int mali_shared_mem_size = MALI_SHARED_MEMORY_DEFAULT_SIZE;
54
55 /* Frame buffer memory to be accessible by Mali GPU */
56 int mali_fb_start = 0;
57 int mali_fb_size = 0;
58
59 /* Mali max job runtime */
60 extern int mali_max_job_runtime;
61
62 /** Start profiling from module load? */
63 int mali_boot_profiling = 0;
64
65 /** Limits for the number of PP cores behind each L2 cache. */
66 int mali_max_pp_cores_group_1 = 0xFF;
67 int mali_max_pp_cores_group_2 = 0xFF;
68
69 int mali_inited_pp_cores_group_1 = 0;
70 int mali_inited_pp_cores_group_2 = 0;
71
72 static _mali_product_id_t global_product_id = _MALI_PRODUCT_ID_UNKNOWN;
73 static uintptr_t global_gpu_base_address = 0;
74 static u32 global_gpu_major_version = 0;
75 static u32 global_gpu_minor_version = 0;
76
77 mali_bool mali_gpu_class_is_mali450 = MALI_FALSE;
78 mali_bool mali_gpu_class_is_mali470 = MALI_FALSE;
79
80 static _mali_osk_errcode_t mali_set_global_gpu_base_address(void)
81 {
82         _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
83
84         global_gpu_base_address = _mali_osk_resource_base_address();
85         if (0 == global_gpu_base_address) {
86                 err = _MALI_OSK_ERR_ITEM_NOT_FOUND;
87         }
88
89         return err;
90 }
91
92 static u32 mali_get_bcast_id(_mali_osk_resource_t *resource_pp)
93 {
94         switch (resource_pp->base - global_gpu_base_address) {
95         case 0x08000:
96         case 0x20000: /* fall-through for aliased mapping */
97                 return 0x01;
98         case 0x0A000:
99         case 0x22000: /* fall-through for aliased mapping */
100                 return 0x02;
101         case 0x0C000:
102         case 0x24000: /* fall-through for aliased mapping */
103                 return 0x04;
104         case 0x0E000:
105         case 0x26000: /* fall-through for aliased mapping */
106                 return 0x08;
107         case 0x28000:
108                 return 0x10;
109         case 0x2A000:
110                 return 0x20;
111         case 0x2C000:
112                 return 0x40;
113         case 0x2E000:
114                 return 0x80;
115         default:
116                 return 0;
117         }
118 }
119
120 static _mali_osk_errcode_t mali_parse_product_info(void)
121 {
122         _mali_osk_resource_t first_pp_resource;
123
124         /* Find the first PP core resource (again) */
125         if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(MALI_OFFSET_PP0, &first_pp_resource)) {
126                 /* Create a dummy PP object for this core so that we can read the version register */
127                 struct mali_group *group = mali_group_create(NULL, NULL, NULL, MALI_DOMAIN_INDEX_PP0);
128                 if (NULL != group) {
129                         struct mali_pp_core *pp_core = mali_pp_create(&first_pp_resource, group, MALI_FALSE, mali_get_bcast_id(&first_pp_resource));
130                         if (NULL != pp_core) {
131                                 u32 pp_version;
132
133                                 pp_version = mali_pp_core_get_version(pp_core);
134
135                                 mali_group_delete(group);
136
137                                 global_gpu_major_version = (pp_version >> 8) & 0xFF;
138                                 global_gpu_minor_version = pp_version & 0xFF;
139
140                                 switch (pp_version >> 16) {
141                                 case MALI200_PP_PRODUCT_ID:
142                                         global_product_id = _MALI_PRODUCT_ID_MALI200;
143                                         MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-200 r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
144                                         MALI_PRINT_ERROR(("Mali-200 is not supported by this driver.\n"));
145                                         _mali_osk_abort();
146                                         break;
147                                 case MALI300_PP_PRODUCT_ID:
148                                         global_product_id = _MALI_PRODUCT_ID_MALI300;
149                                         MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-300 r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
150                                         break;
151                                 case MALI400_PP_PRODUCT_ID:
152                                         global_product_id = _MALI_PRODUCT_ID_MALI400;
153                                         MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-400 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
154                                         break;
155                                 case MALI450_PP_PRODUCT_ID:
156                                         global_product_id = _MALI_PRODUCT_ID_MALI450;
157                                         MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-450 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
158                                         break;
159                                 case MALI470_PP_PRODUCT_ID:
160                                         global_product_id = _MALI_PRODUCT_ID_MALI470;
161                                         MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-470 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
162                                         break;
163                                 default:
164                                         MALI_DEBUG_PRINT(2, ("Found unknown Mali GPU (r%up%u)\n", global_gpu_major_version, global_gpu_minor_version));
165                                         return _MALI_OSK_ERR_FAULT;
166                                 }
167
168                                 return _MALI_OSK_ERR_OK;
169                         } else {
170                                 MALI_PRINT_ERROR(("Failed to create initial PP object\n"));
171                         }
172                 } else {
173                         MALI_PRINT_ERROR(("Failed to create initial group object\n"));
174                 }
175         } else {
176                 MALI_PRINT_ERROR(("First PP core not specified in config file\n"));
177         }
178
179         return _MALI_OSK_ERR_FAULT;
180 }
181
182 static void mali_delete_groups(void)
183 {
184         struct mali_group *group;
185
186         group = mali_group_get_glob_group(0);
187         while (NULL != group) {
188                 mali_group_delete(group);
189                 group = mali_group_get_glob_group(0);
190         }
191
192         MALI_DEBUG_ASSERT(0 == mali_group_get_glob_num_groups());
193 }
194
195 static void mali_delete_l2_cache_cores(void)
196 {
197         struct mali_l2_cache_core *l2;
198
199         l2 = mali_l2_cache_core_get_glob_l2_core(0);
200         while (NULL != l2) {
201                 mali_l2_cache_delete(l2);
202                 l2 = mali_l2_cache_core_get_glob_l2_core(0);
203         }
204
205         MALI_DEBUG_ASSERT(0 == mali_l2_cache_core_get_glob_num_l2_cores());
206 }
207
208 static struct mali_l2_cache_core *mali_create_l2_cache_core(_mali_osk_resource_t *resource, u32 domain_index)
209 {
210         struct mali_l2_cache_core *l2_cache = NULL;
211
212         if (NULL != resource) {
213
214                 MALI_DEBUG_PRINT(3, ("Found L2 cache %s\n", resource->description));
215
216                 l2_cache = mali_l2_cache_create(resource, domain_index);
217                 if (NULL == l2_cache) {
218                         MALI_PRINT_ERROR(("Failed to create L2 cache object\n"));
219                         return NULL;
220                 }
221         }
222         MALI_DEBUG_PRINT(3, ("Created L2 cache core object\n"));
223
224         return l2_cache;
225 }
226
227 static _mali_osk_errcode_t mali_parse_config_l2_cache(void)
228 {
229         struct mali_l2_cache_core *l2_cache = NULL;
230
231         if (mali_is_mali400()) {
232                 _mali_osk_resource_t l2_resource;
233                 if (_MALI_OSK_ERR_OK != _mali_osk_resource_find(MALI400_OFFSET_L2_CACHE0, &l2_resource)) {
234                         MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache in config file\n"));
235                         return _MALI_OSK_ERR_FAULT;
236                 }
237
238                 l2_cache = mali_create_l2_cache_core(&l2_resource, MALI_DOMAIN_INDEX_L20);
239                 if (NULL == l2_cache) {
240                         return _MALI_OSK_ERR_FAULT;
241                 }
242         } else if (mali_is_mali450()) {
243                 /*
244                  * L2 for GP    at 0x10000
245                  * L2 for PP0-3 at 0x01000
246                  * L2 for PP4-7 at 0x11000 (optional)
247                  */
248
249                 _mali_osk_resource_t l2_gp_resource;
250                 _mali_osk_resource_t l2_pp_grp0_resource;
251                 _mali_osk_resource_t l2_pp_grp1_resource;
252
253                 /* Make cluster for GP's L2 */
254                 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(MALI450_OFFSET_L2_CACHE0, &l2_gp_resource)) {
255                         MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for GP\n"));
256                         l2_cache = mali_create_l2_cache_core(&l2_gp_resource, MALI_DOMAIN_INDEX_L20);
257                         if (NULL == l2_cache) {
258                                 return _MALI_OSK_ERR_FAULT;
259                         }
260                 } else {
261                         MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for GP in config file\n"));
262                         return _MALI_OSK_ERR_FAULT;
263                 }
264
265                 /* Find corresponding l2 domain */
266                 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(MALI450_OFFSET_L2_CACHE1, &l2_pp_grp0_resource)) {
267                         MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 0\n"));
268                         l2_cache = mali_create_l2_cache_core(&l2_pp_grp0_resource, MALI_DOMAIN_INDEX_L21);
269                         if (NULL == l2_cache) {
270                                 return _MALI_OSK_ERR_FAULT;
271                         }
272                 } else {
273                         MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for PP group 0 in config file\n"));
274                         return _MALI_OSK_ERR_FAULT;
275                 }
276
277                 /* Second PP core group is optional, don't fail if we don't find it */
278                 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(MALI450_OFFSET_L2_CACHE2, &l2_pp_grp1_resource)) {
279                         MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 1\n"));
280                         l2_cache = mali_create_l2_cache_core(&l2_pp_grp1_resource, MALI_DOMAIN_INDEX_L22);
281                         if (NULL == l2_cache) {
282                                 return _MALI_OSK_ERR_FAULT;
283                         }
284                 }
285         } else if (mali_is_mali470()) {
286                 _mali_osk_resource_t l2c1_resource;
287
288                 /* Make cluster for L2C1 */
289                 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(MALI470_OFFSET_L2_CACHE1, &l2c1_resource)) {
290                         MALI_DEBUG_PRINT(3, ("Creating Mali-470 L2 cache 1\n"));
291                         l2_cache = mali_create_l2_cache_core(&l2c1_resource, MALI_DOMAIN_INDEX_L21);
292                         if (NULL == l2_cache) {
293                                 return _MALI_OSK_ERR_FAULT;
294                         }
295                 } else {
296                         MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for L2C1\n"));
297                         return _MALI_OSK_ERR_FAULT;
298                 }
299         }
300
301         return _MALI_OSK_ERR_OK;
302 }
303
304 static struct mali_group *mali_create_group(struct mali_l2_cache_core *cache,
305                 _mali_osk_resource_t *resource_mmu,
306                 _mali_osk_resource_t *resource_gp,
307                 _mali_osk_resource_t *resource_pp,
308                 u32 domain_index)
309 {
310         struct mali_mmu_core *mmu;
311         struct mali_group *group;
312
313         MALI_DEBUG_PRINT(3, ("Starting new group for MMU %s\n", resource_mmu->description));
314
315         /* Create the group object */
316         group = mali_group_create(cache, NULL, NULL, domain_index);
317         if (NULL == group) {
318                 MALI_PRINT_ERROR(("Failed to create group object for MMU %s\n", resource_mmu->description));
319                 return NULL;
320         }
321
322         /* Create the MMU object inside group */
323         mmu = mali_mmu_create(resource_mmu, group, MALI_FALSE);
324         if (NULL == mmu) {
325                 MALI_PRINT_ERROR(("Failed to create MMU object\n"));
326                 mali_group_delete(group);
327                 return NULL;
328         }
329
330         if (NULL != resource_gp) {
331                 /* Create the GP core object inside this group */
332                 struct mali_gp_core *gp_core = mali_gp_create(resource_gp, group);
333                 if (NULL == gp_core) {
334                         /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
335                         MALI_PRINT_ERROR(("Failed to create GP object\n"));
336                         mali_group_delete(group);
337                         return NULL;
338                 }
339         }
340
341         if (NULL != resource_pp) {
342                 struct mali_pp_core *pp_core;
343
344                 /* Create the PP core object inside this group */
345                 pp_core = mali_pp_create(resource_pp, group, MALI_FALSE, mali_get_bcast_id(resource_pp));
346                 if (NULL == pp_core) {
347                         /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
348                         MALI_PRINT_ERROR(("Failed to create PP object\n"));
349                         mali_group_delete(group);
350                         return NULL;
351                 }
352         }
353
354         return group;
355 }
356
357 static _mali_osk_errcode_t mali_create_virtual_group(_mali_osk_resource_t *resource_mmu_pp_bcast,
358                 _mali_osk_resource_t *resource_pp_bcast,
359                 _mali_osk_resource_t *resource_dlbu,
360                 _mali_osk_resource_t *resource_bcast)
361 {
362         struct mali_mmu_core *mmu_pp_bcast_core;
363         struct mali_pp_core *pp_bcast_core;
364         struct mali_dlbu_core *dlbu_core;
365         struct mali_bcast_unit *bcast_core;
366         struct mali_group *group;
367
368         MALI_DEBUG_PRINT(2, ("Starting new virtual group for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description));
369
370         /* Create the DLBU core object */
371         dlbu_core = mali_dlbu_create(resource_dlbu);
372         if (NULL == dlbu_core) {
373                 MALI_PRINT_ERROR(("Failed to create DLBU object \n"));
374                 return _MALI_OSK_ERR_FAULT;
375         }
376
377         /* Create the Broadcast unit core */
378         bcast_core = mali_bcast_unit_create(resource_bcast);
379         if (NULL == bcast_core) {
380                 MALI_PRINT_ERROR(("Failed to create Broadcast unit object!\n"));
381                 mali_dlbu_delete(dlbu_core);
382                 return _MALI_OSK_ERR_FAULT;
383         }
384
385         /* Create the group object */
386 #if defined(DEBUG)
387         /* Get a physical PP group to temporarily add to broadcast unit.  IRQ
388          * verification needs a physical group in the broadcast unit to test
389          * the broadcast unit interrupt line. */
390         {
391                 struct mali_group *phys_group = NULL;
392                 int i;
393                 for (i = 0; i < mali_group_get_glob_num_groups(); i++) {
394                         phys_group = mali_group_get_glob_group(i);
395                         if (NULL != mali_group_get_pp_core(phys_group)) break;
396                 }
397                 MALI_DEBUG_ASSERT(NULL != mali_group_get_pp_core(phys_group));
398
399                 /* Add the group temporarily to the broadcast, and update the
400                  * broadcast HW. Since the HW is not updated when removing the
401                  * group the IRQ check will work when the virtual PP is created
402                  * later.
403                  *
404                  * When the virtual group gets populated, the actually used
405                  * groups will be added to the broadcast unit and the HW will
406                  * be updated.
407                  */
408                 mali_bcast_add_group(bcast_core, phys_group);
409                 mali_bcast_reset(bcast_core);
410                 mali_bcast_remove_group(bcast_core, phys_group);
411         }
412 #endif /* DEBUG */
413         group = mali_group_create(NULL, dlbu_core, bcast_core, MALI_DOMAIN_INDEX_DUMMY);
414         if (NULL == group) {
415                 MALI_PRINT_ERROR(("Failed to create group object for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description));
416                 mali_bcast_unit_delete(bcast_core);
417                 mali_dlbu_delete(dlbu_core);
418                 return _MALI_OSK_ERR_FAULT;
419         }
420
421         /* Create the MMU object inside group */
422         mmu_pp_bcast_core = mali_mmu_create(resource_mmu_pp_bcast, group, MALI_TRUE);
423         if (NULL == mmu_pp_bcast_core) {
424                 MALI_PRINT_ERROR(("Failed to create MMU PP broadcast object\n"));
425                 mali_group_delete(group);
426                 return _MALI_OSK_ERR_FAULT;
427         }
428
429         /* Create the PP core object inside this group */
430         pp_bcast_core = mali_pp_create(resource_pp_bcast, group, MALI_TRUE, 0);
431         if (NULL == pp_bcast_core) {
432                 /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
433                 MALI_PRINT_ERROR(("Failed to create PP object\n"));
434                 mali_group_delete(group);
435                 return _MALI_OSK_ERR_FAULT;
436         }
437
438         return _MALI_OSK_ERR_OK;
439 }
440
441 static _mali_osk_errcode_t mali_parse_config_groups(void)
442 {
443         struct mali_group *group;
444         int cluster_id_gp = 0;
445         int cluster_id_pp_grp0 = 0;
446         int cluster_id_pp_grp1 = 0;
447         int i;
448
449         _mali_osk_resource_t resource_gp;
450         _mali_osk_resource_t resource_gp_mmu;
451         _mali_osk_resource_t resource_pp[8];
452         _mali_osk_resource_t resource_pp_mmu[8];
453         _mali_osk_resource_t resource_pp_mmu_bcast;
454         _mali_osk_resource_t resource_pp_bcast;
455         _mali_osk_resource_t resource_dlbu;
456         _mali_osk_resource_t resource_bcast;
457         _mali_osk_errcode_t resource_gp_found;
458         _mali_osk_errcode_t resource_gp_mmu_found;
459         _mali_osk_errcode_t resource_pp_found[8];
460         _mali_osk_errcode_t resource_pp_mmu_found[8];
461         _mali_osk_errcode_t resource_pp_mmu_bcast_found;
462         _mali_osk_errcode_t resource_pp_bcast_found;
463         _mali_osk_errcode_t resource_dlbu_found;
464         _mali_osk_errcode_t resource_bcast_found;
465
466         if (!(mali_is_mali400() || mali_is_mali450() || mali_is_mali470())) {
467                 /* No known HW core */
468                 return _MALI_OSK_ERR_FAULT;
469         }
470
471         if (MALI_MAX_JOB_RUNTIME_DEFAULT == mali_max_job_runtime) {
472                 /* Group settings are not overridden by module parameters, so use device settings */
473                 _mali_osk_device_data data = { 0, };
474
475                 if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
476                         /* Use device specific settings (if defined) */
477                         if (0 != data.max_job_runtime) {
478                                 mali_max_job_runtime = data.max_job_runtime;
479                         }
480                 }
481         }
482
483         if (mali_is_mali450()) {
484                 /* Mali-450 have separate L2s for GP, and PP core group(s) */
485                 cluster_id_pp_grp0 = 1;
486                 cluster_id_pp_grp1 = 2;
487         }
488
489         resource_gp_found = _mali_osk_resource_find(MALI_OFFSET_GP, &resource_gp);
490         resource_gp_mmu_found = _mali_osk_resource_find(MALI_OFFSET_GP_MMU, &resource_gp_mmu);
491         resource_pp_found[0] = _mali_osk_resource_find(MALI_OFFSET_PP0, &(resource_pp[0]));
492         resource_pp_found[1] = _mali_osk_resource_find(MALI_OFFSET_PP1, &(resource_pp[1]));
493         resource_pp_found[2] = _mali_osk_resource_find(MALI_OFFSET_PP2, &(resource_pp[2]));
494         resource_pp_found[3] = _mali_osk_resource_find(MALI_OFFSET_PP3, &(resource_pp[3]));
495         resource_pp_found[4] = _mali_osk_resource_find(MALI_OFFSET_PP4, &(resource_pp[4]));
496         resource_pp_found[5] = _mali_osk_resource_find(MALI_OFFSET_PP5, &(resource_pp[5]));
497         resource_pp_found[6] = _mali_osk_resource_find(MALI_OFFSET_PP6, &(resource_pp[6]));
498         resource_pp_found[7] = _mali_osk_resource_find(MALI_OFFSET_PP7, &(resource_pp[7]));
499         resource_pp_mmu_found[0] = _mali_osk_resource_find(MALI_OFFSET_PP0_MMU, &(resource_pp_mmu[0]));
500         resource_pp_mmu_found[1] = _mali_osk_resource_find(MALI_OFFSET_PP1_MMU, &(resource_pp_mmu[1]));
501         resource_pp_mmu_found[2] = _mali_osk_resource_find(MALI_OFFSET_PP2_MMU, &(resource_pp_mmu[2]));
502         resource_pp_mmu_found[3] = _mali_osk_resource_find(MALI_OFFSET_PP3_MMU, &(resource_pp_mmu[3]));
503         resource_pp_mmu_found[4] = _mali_osk_resource_find(MALI_OFFSET_PP4_MMU, &(resource_pp_mmu[4]));
504         resource_pp_mmu_found[5] = _mali_osk_resource_find(MALI_OFFSET_PP5_MMU, &(resource_pp_mmu[5]));
505         resource_pp_mmu_found[6] = _mali_osk_resource_find(MALI_OFFSET_PP6_MMU, &(resource_pp_mmu[6]));
506         resource_pp_mmu_found[7] = _mali_osk_resource_find(MALI_OFFSET_PP7_MMU, &(resource_pp_mmu[7]));
507
508
509         if (mali_is_mali450() || mali_is_mali470()) {
510                 resource_bcast_found = _mali_osk_resource_find(MALI_OFFSET_BCAST, &resource_bcast);
511                 resource_dlbu_found = _mali_osk_resource_find(MALI_OFFSET_DLBU, &resource_dlbu);
512                 resource_pp_mmu_bcast_found = _mali_osk_resource_find(MALI_OFFSET_PP_BCAST_MMU, &resource_pp_mmu_bcast);
513                 resource_pp_bcast_found = _mali_osk_resource_find(MALI_OFFSET_PP_BCAST, &resource_pp_bcast);
514
515                 if (_MALI_OSK_ERR_OK != resource_bcast_found ||
516                     _MALI_OSK_ERR_OK != resource_dlbu_found ||
517                     _MALI_OSK_ERR_OK != resource_pp_mmu_bcast_found ||
518                     _MALI_OSK_ERR_OK != resource_pp_bcast_found) {
519                         /* Missing mandatory core(s) for Mali-450 or Mali-470 */
520                         MALI_DEBUG_PRINT(2, ("Missing mandatory resources, Mali-450 needs DLBU, Broadcast unit, virtual PP core and virtual MMU\n"));
521                         return _MALI_OSK_ERR_FAULT;
522                 }
523         }
524
525         if (_MALI_OSK_ERR_OK != resource_gp_found ||
526             _MALI_OSK_ERR_OK != resource_gp_mmu_found ||
527             _MALI_OSK_ERR_OK != resource_pp_found[0] ||
528             _MALI_OSK_ERR_OK != resource_pp_mmu_found[0]) {
529                 /* Missing mandatory core(s) */
530                 MALI_DEBUG_PRINT(2, ("Missing mandatory resource, need at least one GP and one PP, both with a separate MMU\n"));
531                 return _MALI_OSK_ERR_FAULT;
532         }
533
534         MALI_DEBUG_ASSERT(1 <= mali_l2_cache_core_get_glob_num_l2_cores());
535         group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_gp), &resource_gp_mmu, &resource_gp, NULL, MALI_DOMAIN_INDEX_GP);
536         if (NULL == group) {
537                 return _MALI_OSK_ERR_FAULT;
538         }
539
540         /* Create group for first (and mandatory) PP core */
541         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 */
542         group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[0], NULL, &resource_pp[0], MALI_DOMAIN_INDEX_PP0);
543         if (NULL == group) {
544                 return _MALI_OSK_ERR_FAULT;
545         }
546
547         mali_inited_pp_cores_group_1++;
548
549         /* Create groups for rest of the cores in the first PP core group */
550         for (i = 1; i < 4; i++) { /* First half of the PP cores belong to first core group */
551                 if (mali_inited_pp_cores_group_1 < mali_max_pp_cores_group_1) {
552                         if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[i]) {
553                                 group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[i], NULL, &resource_pp[i], MALI_DOMAIN_INDEX_PP0 + i);
554                                 if (NULL == group) {
555                                         return _MALI_OSK_ERR_FAULT;
556                                 }
557
558                                 mali_inited_pp_cores_group_1++;
559                         }
560                 }
561         }
562
563         /* Create groups for cores in the second PP core group */
564         for (i = 4; i < 8; i++) { /* Second half of the PP cores belong to second core group */
565                 if (mali_inited_pp_cores_group_2 < mali_max_pp_cores_group_2) {
566                         if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[i]) {
567                                 MALI_DEBUG_ASSERT(mali_l2_cache_core_get_glob_num_l2_cores() >= 2); /* Only Mali-450 have a second core group */
568                                 group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp1), &resource_pp_mmu[i], NULL, &resource_pp[i], MALI_DOMAIN_INDEX_PP0 + i);
569                                 if (NULL == group) {
570                                         return _MALI_OSK_ERR_FAULT;
571                                 }
572
573                                 mali_inited_pp_cores_group_2++;
574                         }
575                 }
576         }
577
578         if (mali_is_mali450() || mali_is_mali470()) {
579                 _mali_osk_errcode_t err = mali_create_virtual_group(&resource_pp_mmu_bcast, &resource_pp_bcast, &resource_dlbu, &resource_bcast);
580                 if (_MALI_OSK_ERR_OK != err) {
581                         return err;
582                 }
583         }
584
585         mali_max_pp_cores_group_1 = mali_inited_pp_cores_group_1;
586         mali_max_pp_cores_group_2 = mali_inited_pp_cores_group_2;
587         MALI_DEBUG_PRINT(2, ("%d+%d PP cores initialized\n", mali_inited_pp_cores_group_1, mali_inited_pp_cores_group_2));
588
589         return _MALI_OSK_ERR_OK;
590 }
591
592 static _mali_osk_errcode_t mali_check_shared_interrupts(void)
593 {
594 #if !defined(CONFIG_MALI_SHARED_INTERRUPTS)
595         if (MALI_TRUE == _mali_osk_shared_interrupts()) {
596                 MALI_PRINT_ERROR(("Shared interrupts detected, but driver support is not enabled\n"));
597                 return _MALI_OSK_ERR_FAULT;
598         }
599 #endif /* !defined(CONFIG_MALI_SHARED_INTERRUPTS) */
600
601         /* It is OK to compile support for shared interrupts even if Mali is not using it. */
602         return _MALI_OSK_ERR_OK;
603 }
604
605 static _mali_osk_errcode_t mali_parse_config_pmu(void)
606 {
607         _mali_osk_resource_t resource_pmu;
608
609         MALI_DEBUG_ASSERT(0 != global_gpu_base_address);
610
611         if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(MALI_OFFSET_PMU, &resource_pmu)) {
612                 struct mali_pmu_core *pmu;
613
614                 pmu = mali_pmu_create(&resource_pmu);
615                 if (NULL == pmu) {
616                         MALI_PRINT_ERROR(("Failed to create PMU\n"));
617                         return _MALI_OSK_ERR_FAULT;
618                 }
619         }
620
621         /* It's ok if the PMU doesn't exist */
622         return _MALI_OSK_ERR_OK;
623 }
624
625 static _mali_osk_errcode_t mali_parse_config_memory(void)
626 {
627         _mali_osk_device_data data = { 0, };
628         _mali_osk_errcode_t ret;
629
630         /* The priority of setting the value of mali_shared_mem_size,
631          * mali_dedicated_mem_start and mali_dedicated_mem_size:
632          * 1. module parameter;
633          * 2. platform data;
634          * 3. default value;
635          **/
636         if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
637                 /* Memory settings are not overridden by module parameters, so use device settings */
638                 if (0 == mali_dedicated_mem_start && 0 == mali_dedicated_mem_size) {
639                         /* Use device specific settings (if defined) */
640                         mali_dedicated_mem_start = data.dedicated_mem_start;
641                         mali_dedicated_mem_size = data.dedicated_mem_size;
642                 }
643
644                 if (MALI_SHARED_MEMORY_DEFAULT_SIZE == mali_shared_mem_size &&
645                     0 != data.shared_mem_size) {
646                         mali_shared_mem_size = data.shared_mem_size;
647                 }
648         }
649
650         if (0 < mali_dedicated_mem_size && 0 != mali_dedicated_mem_start) {
651                 MALI_DEBUG_PRINT(2, ("Mali memory settings (dedicated: 0x%08X@0x%08X)\n",
652                                      mali_dedicated_mem_size, mali_dedicated_mem_start));
653
654                 /* Dedicated memory */
655                 ret = mali_memory_core_resource_dedicated_memory(mali_dedicated_mem_start, mali_dedicated_mem_size);
656                 if (_MALI_OSK_ERR_OK != ret) {
657                         MALI_PRINT_ERROR(("Failed to register dedicated memory\n"));
658                         mali_memory_terminate();
659                         return ret;
660                 }
661         }
662
663         if (0 < mali_shared_mem_size) {
664                 MALI_DEBUG_PRINT(2, ("Mali memory settings (shared: 0x%08X)\n", mali_shared_mem_size));
665
666                 /* Shared OS memory */
667                 ret = mali_memory_core_resource_os_memory(mali_shared_mem_size);
668                 if (_MALI_OSK_ERR_OK != ret) {
669                         MALI_PRINT_ERROR(("Failed to register shared OS memory\n"));
670                         mali_memory_terminate();
671                         return ret;
672                 }
673         }
674
675         if (0 == mali_fb_start && 0 == mali_fb_size) {
676                 /* Frame buffer settings are not overridden by module parameters, so use device settings */
677                 _mali_osk_device_data data = { 0, };
678
679                 if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
680                         /* Use device specific settings (if defined) */
681                         mali_fb_start = data.fb_start;
682                         mali_fb_size = data.fb_size;
683                 }
684
685                 MALI_DEBUG_PRINT(2, ("Using device defined frame buffer settings (0x%08X@0x%08X)\n",
686                                      mali_fb_size, mali_fb_start));
687         } else {
688                 MALI_DEBUG_PRINT(2, ("Using module defined frame buffer settings (0x%08X@0x%08X)\n",
689                                      mali_fb_size, mali_fb_start));
690         }
691
692         if (0 != mali_fb_size) {
693                 /* Register frame buffer */
694                 ret = mali_mem_validation_add_range(mali_fb_start, mali_fb_size);
695                 if (_MALI_OSK_ERR_OK != ret) {
696                         MALI_PRINT_ERROR(("Failed to register frame buffer memory region\n"));
697                         mali_memory_terminate();
698                         return ret;
699                 }
700         }
701
702         return _MALI_OSK_ERR_OK;
703 }
704
705 static void mali_detect_gpu_class(void)
706 {
707         if (_mali_osk_identify_gpu_resource() == 0x450)
708                 mali_gpu_class_is_mali450 = MALI_TRUE;
709
710         if (_mali_osk_identify_gpu_resource() == 0x470)
711                 mali_gpu_class_is_mali470 = MALI_TRUE;
712 }
713
714 static _mali_osk_errcode_t mali_init_hw_reset(void)
715 {
716 #if (defined(CONFIG_MALI450) || defined(CONFIG_MALI470))
717         _mali_osk_resource_t resource_bcast;
718
719         /* Ensure broadcast unit is in a good state before we start creating
720          * groups and cores.
721          */
722         if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(MALI_OFFSET_BCAST, &resource_bcast)) {
723                 struct mali_bcast_unit *bcast_core;
724
725                 bcast_core = mali_bcast_unit_create(&resource_bcast);
726                 if (NULL == bcast_core) {
727                         MALI_PRINT_ERROR(("Failed to create Broadcast unit object!\n"));
728                         return _MALI_OSK_ERR_FAULT;
729                 }
730                 mali_bcast_unit_delete(bcast_core);
731         }
732 #endif /* (defined(CONFIG_MALI450) || defined(CONFIG_MALI470)) */
733
734         return _MALI_OSK_ERR_OK;
735 }
736
737 _mali_osk_errcode_t mali_initialize_subsystems(void)
738 {
739         _mali_osk_errcode_t err;
740
741 #ifdef CONFIG_MALI_DT
742         err = _mali_osk_resource_initialize();
743         if (_MALI_OSK_ERR_OK != err) {
744                 mali_terminate_subsystems();
745                 return err;
746         }
747 #endif
748
749         mali_pp_job_initialize();
750
751         mali_timeline_initialize();
752
753         err = mali_session_initialize();
754         if (_MALI_OSK_ERR_OK != err) {
755                 mali_terminate_subsystems();
756                 return err;
757         }
758
759 #if defined(CONFIG_MALI400_PROFILING)
760         err = _mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE);
761         if (_MALI_OSK_ERR_OK != err) {
762                 /* No biggie if we weren't able to initialize the profiling */
763                 MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n"));
764         }
765 #endif
766
767         err = mali_memory_initialize();
768         if (_MALI_OSK_ERR_OK != err) {
769                 mali_terminate_subsystems();
770                 return err;
771         }
772
773         err = mali_executor_initialize();
774         if (_MALI_OSK_ERR_OK != err) {
775                 mali_terminate_subsystems();
776                 return err;
777         }
778
779         err = mali_scheduler_initialize();
780         if (_MALI_OSK_ERR_OK != err) {
781                 mali_terminate_subsystems();
782                 return err;
783         }
784
785         /* Configure memory early, needed by mali_mmu_initialize. */
786         err = mali_parse_config_memory();
787         if (_MALI_OSK_ERR_OK != err) {
788                 mali_terminate_subsystems();
789                 return err;
790         }
791
792         err = mali_set_global_gpu_base_address();
793         if (_MALI_OSK_ERR_OK != err) {
794                 mali_terminate_subsystems();
795                 return err;
796         }
797
798         /* Detect GPU class (uses L2 cache count) */
799         mali_detect_gpu_class();
800
801         err = mali_check_shared_interrupts();
802         if (_MALI_OSK_ERR_OK != err) {
803                 mali_terminate_subsystems();
804                 return err;
805         }
806
807         /* Initialize the MALI PMU (will not touch HW!) */
808         err = mali_parse_config_pmu();
809         if (_MALI_OSK_ERR_OK != err) {
810                 mali_terminate_subsystems();
811                 return err;
812         }
813
814         /* Initialize the power management module */
815         err = mali_pm_initialize();
816         if (_MALI_OSK_ERR_OK != err) {
817                 mali_terminate_subsystems();
818                 return err;
819         }
820
821         /* Make sure the entire GPU stays on for the rest of this function */
822         mali_pm_init_begin();
823
824         /* Ensure HW is in a good state before starting to access cores. */
825         err = mali_init_hw_reset();
826         if (_MALI_OSK_ERR_OK != err) {
827                 mali_terminate_subsystems();
828                 return err;
829         }
830
831         /* Detect which Mali GPU we are dealing with */
832         err = mali_parse_product_info();
833         if (_MALI_OSK_ERR_OK != err) {
834                 mali_pm_init_end();
835                 mali_terminate_subsystems();
836                 return err;
837         }
838
839         /* The global_product_id is now populated with the correct Mali GPU */
840
841         /* Start configuring the actual Mali hardware. */
842
843         err = mali_mmu_initialize();
844         if (_MALI_OSK_ERR_OK != err) {
845                 mali_pm_init_end();
846                 mali_terminate_subsystems();
847                 return err;
848         }
849
850         if (mali_is_mali450() || mali_is_mali470()) {
851                 err = mali_dlbu_initialize();
852                 if (_MALI_OSK_ERR_OK != err) {
853                         mali_pm_init_end();
854                         mali_terminate_subsystems();
855                         return err;
856                 }
857         }
858
859         err = mali_parse_config_l2_cache();
860         if (_MALI_OSK_ERR_OK != err) {
861                 mali_pm_init_end();
862                 mali_terminate_subsystems();
863                 return err;
864         }
865
866         err = mali_parse_config_groups();
867         if (_MALI_OSK_ERR_OK != err) {
868                 mali_pm_init_end();
869                 mali_terminate_subsystems();
870                 return err;
871         }
872
873         /* Move groups into executor */
874         mali_executor_populate();
875
876         /* Need call after all group has assigned a domain */
877         mali_pm_power_cost_setup();
878
879         /* Initialize the GPU timer */
880         err = mali_control_timer_init();
881         if (_MALI_OSK_ERR_OK != err) {
882                 mali_pm_init_end();
883                 mali_terminate_subsystems();
884                 return err;
885         }
886
887         /* Initialize the GPU utilization tracking */
888         err = mali_utilization_init();
889         if (_MALI_OSK_ERR_OK != err) {
890                 mali_pm_init_end();
891                 mali_terminate_subsystems();
892                 return err;
893         }
894
895 #if defined(CONFIG_MALI_DVFS)
896         err = mali_dvfs_policy_init();
897         if (_MALI_OSK_ERR_OK != err) {
898                 mali_pm_init_end();
899                 mali_terminate_subsystems();
900                 return err;
901         }
902 #endif
903
904         /* Allowing the system to be turned off */
905         mali_pm_init_end();
906
907         return _MALI_OSK_ERR_OK; /* all ok */
908 }
909
910 void mali_terminate_subsystems(void)
911 {
912         struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
913
914         MALI_DEBUG_PRINT(2, ("terminate_subsystems() called\n"));
915
916         mali_utilization_term();
917         mali_control_timer_term();
918
919         mali_executor_depopulate();
920         mali_delete_groups(); /* Delete groups not added to executor */
921         mali_executor_terminate();
922
923         mali_scheduler_terminate();
924         mali_pp_job_terminate();
925         mali_delete_l2_cache_cores();
926         mali_mmu_terminate();
927
928         if (mali_is_mali450() || mali_is_mali470()) {
929                 mali_dlbu_terminate();
930         }
931
932         mali_pm_terminate();
933
934         if (NULL != pmu) {
935                 mali_pmu_delete(pmu);
936         }
937
938 #if defined(CONFIG_MALI400_PROFILING)
939         _mali_osk_profiling_term();
940 #endif
941
942         mali_memory_terminate();
943
944         mali_session_terminate();
945
946         mali_timeline_terminate();
947
948         global_gpu_base_address = 0;
949 }
950
951 _mali_product_id_t mali_kernel_core_get_product_id(void)
952 {
953         return global_product_id;
954 }
955
956 u32 mali_kernel_core_get_gpu_major_version(void)
957 {
958         return global_gpu_major_version;
959 }
960
961 u32 mali_kernel_core_get_gpu_minor_version(void)
962 {
963         return global_gpu_minor_version;
964 }
965
966 _mali_osk_errcode_t _mali_ukk_get_api_version(_mali_uk_get_api_version_s *args)
967 {
968         MALI_DEBUG_ASSERT_POINTER(args);
969         MALI_DEBUG_ASSERT(NULL != (void *)(uintptr_t)args->ctx);
970
971         /* check compatability */
972         if (args->version == _MALI_UK_API_VERSION) {
973                 args->compatible = 1;
974         } else {
975                 args->compatible = 0;
976         }
977
978         args->version = _MALI_UK_API_VERSION; /* report our version */
979
980         /* success regardless of being compatible or not */
981         MALI_SUCCESS;
982 }
983
984 _mali_osk_errcode_t _mali_ukk_get_api_version_v2(_mali_uk_get_api_version_v2_s *args)
985 {
986         MALI_DEBUG_ASSERT_POINTER(args);
987         MALI_DEBUG_ASSERT(NULL != (void *)(uintptr_t)args->ctx);
988
989         /* check compatability */
990         if (args->version == _MALI_UK_API_VERSION) {
991                 args->compatible = 1;
992         } else {
993                 args->compatible = 0;
994         }
995
996         args->version = _MALI_UK_API_VERSION; /* report our version */
997
998         /* success regardless of being compatible or not */
999         return _MALI_OSK_ERR_OK;
1000 }
1001
1002 _mali_osk_errcode_t _mali_ukk_wait_for_notification(_mali_uk_wait_for_notification_s *args)
1003 {
1004         _mali_osk_errcode_t err;
1005         _mali_osk_notification_t *notification;
1006         _mali_osk_notification_queue_t *queue;
1007         struct mali_session_data *session;
1008
1009         /* check input */
1010         MALI_DEBUG_ASSERT_POINTER(args);
1011         MALI_DEBUG_ASSERT(NULL != (void *)(uintptr_t)args->ctx);
1012
1013         session = (struct mali_session_data *)(uintptr_t)args->ctx;
1014         queue = session->ioctl_queue;
1015
1016         /* if the queue does not exist we're currently shutting down */
1017         if (NULL == queue) {
1018                 MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n"));
1019                 args->type = _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS;
1020                 return _MALI_OSK_ERR_OK;
1021         }
1022
1023         /* receive a notification, might sleep */
1024         err = _mali_osk_notification_queue_receive(queue, &notification);
1025         if (_MALI_OSK_ERR_OK != err) {
1026                 MALI_ERROR(err); /* errcode returned, pass on to caller */
1027         }
1028
1029         /* copy the buffer to the user */
1030         args->type = (_mali_uk_notification_type)notification->notification_type;
1031         _mali_osk_memcpy(&args->data, notification->result_buffer, notification->result_buffer_size);
1032
1033         /* finished with the notification */
1034         _mali_osk_notification_delete(notification);
1035
1036         return _MALI_OSK_ERR_OK; /* all ok */
1037 }
1038
1039 _mali_osk_errcode_t _mali_ukk_post_notification(_mali_uk_post_notification_s *args)
1040 {
1041         _mali_osk_notification_t *notification;
1042         _mali_osk_notification_queue_t *queue;
1043         struct mali_session_data *session;
1044
1045         /* check input */
1046         MALI_DEBUG_ASSERT_POINTER(args);
1047         MALI_DEBUG_ASSERT(NULL != (void *)(uintptr_t)args->ctx);
1048
1049         session = (struct mali_session_data *)(uintptr_t)args->ctx;
1050         queue = session->ioctl_queue;
1051
1052         /* if the queue does not exist we're currently shutting down */
1053         if (NULL == queue) {
1054                 MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n"));
1055                 return _MALI_OSK_ERR_OK;
1056         }
1057
1058         notification = _mali_osk_notification_create(args->type, 0);
1059         if (NULL == notification) {
1060                 MALI_PRINT_ERROR(("Failed to create notification object\n"));
1061                 return _MALI_OSK_ERR_NOMEM;
1062         }
1063
1064         _mali_osk_notification_queue_send(queue, notification);
1065
1066         return _MALI_OSK_ERR_OK; /* all ok */
1067 }
1068
1069 _mali_osk_errcode_t _mali_ukk_pending_submit(_mali_uk_pending_submit_s *args)
1070 {
1071         wait_queue_head_t *queue;
1072
1073         /* check input */
1074         MALI_DEBUG_ASSERT_POINTER(args);
1075         MALI_DEBUG_ASSERT(NULL != (void *)(uintptr_t)args->ctx);
1076
1077         queue = mali_session_get_wait_queue();
1078
1079         /* check pending big job number, might sleep if larger than MAX allowed number */
1080         if (wait_event_interruptible(*queue, MALI_MAX_PENDING_BIG_JOB > mali_scheduler_job_gp_big_job_count())) {
1081                 return _MALI_OSK_ERR_RESTARTSYSCALL;
1082         }
1083
1084         return _MALI_OSK_ERR_OK; /* all ok */
1085 }
1086
1087
1088 _mali_osk_errcode_t _mali_ukk_request_high_priority(_mali_uk_request_high_priority_s *args)
1089 {
1090         struct mali_session_data *session;
1091
1092         MALI_DEBUG_ASSERT_POINTER(args);
1093         MALI_DEBUG_ASSERT(NULL != (void *)(uintptr_t)args->ctx);
1094
1095         session = (struct mali_session_data *)(uintptr_t)args->ctx;
1096
1097         if (!session->use_high_priority_job_queue) {
1098                 session->use_high_priority_job_queue = MALI_TRUE;
1099                 MALI_DEBUG_PRINT(2, ("Session 0x%08X with pid %d was granted higher priority.\n", session, _mali_osk_get_pid()));
1100         }
1101
1102         return _MALI_OSK_ERR_OK;
1103 }
1104
1105 _mali_osk_errcode_t _mali_ukk_open(void **context)
1106 {
1107         u32 i;
1108         struct mali_session_data *session;
1109
1110         /* allocated struct to track this session */
1111         session = (struct mali_session_data *)_mali_osk_calloc(1, sizeof(struct mali_session_data));
1112         MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_NOMEM);
1113
1114         MALI_DEBUG_PRINT(3, ("Session starting\n"));
1115
1116         /* create a response queue for this session */
1117         session->ioctl_queue = _mali_osk_notification_queue_init();
1118         if (NULL == session->ioctl_queue) {
1119                 goto err;
1120         }
1121
1122         session->page_directory = mali_mmu_pagedir_alloc();
1123         if (NULL == session->page_directory) {
1124                 goto err_mmu;
1125         }
1126
1127         if (_MALI_OSK_ERR_OK != mali_mmu_pagedir_map(session->page_directory, MALI_DLBU_VIRT_ADDR, _MALI_OSK_MALI_PAGE_SIZE)) {
1128                 MALI_PRINT_ERROR(("Failed to map DLBU page into session\n"));
1129                 goto err_mmu;
1130         }
1131
1132         if (0 != mali_dlbu_phys_addr) {
1133                 mali_mmu_pagedir_update(session->page_directory, MALI_DLBU_VIRT_ADDR, mali_dlbu_phys_addr,
1134                                         _MALI_OSK_MALI_PAGE_SIZE, MALI_MMU_FLAGS_DEFAULT);
1135         }
1136
1137         if (_MALI_OSK_ERR_OK != mali_memory_session_begin(session)) {
1138                 goto err_session;
1139         }
1140
1141         /* Create soft system. */
1142         session->soft_job_system = mali_soft_job_system_create(session);
1143         if (NULL == session->soft_job_system) {
1144                 goto err_soft;
1145         }
1146
1147         /* Create timeline system. */
1148         session->timeline_system = mali_timeline_system_create(session);
1149         if (NULL == session->timeline_system) {
1150                 goto err_time_line;
1151         }
1152
1153 #if defined(CONFIG_MALI_DVFS)
1154         _mali_osk_atomic_init(&session->number_of_window_jobs, 0);
1155 #endif
1156
1157         session->use_high_priority_job_queue = MALI_FALSE;
1158
1159         /* Initialize list of PP jobs on this session. */
1160         _MALI_OSK_INIT_LIST_HEAD(&session->pp_job_list);
1161
1162         /* Initialize the pp_job_fb_lookup_list array used to quickly lookup jobs from a given frame builder */
1163         for (i = 0; i < MALI_PP_JOB_FB_LOOKUP_LIST_SIZE; ++i) {
1164                 _MALI_OSK_INIT_LIST_HEAD(&session->pp_job_fb_lookup_list[i]);
1165         }
1166
1167         session->pid = _mali_osk_get_pid();
1168         session->comm = _mali_osk_get_comm();
1169         session->max_mali_mem_allocated_size = 0;
1170         for (i = 0; i < MALI_MEM_TYPE_MAX; i ++) {
1171                 atomic_set(&session->mali_mem_array[i], 0);
1172         }
1173         atomic_set(&session->mali_mem_allocated_pages, 0);
1174         *context = (void *)session;
1175
1176         /* Add session to the list of all sessions. */
1177         mali_session_add(session);
1178
1179         MALI_DEBUG_PRINT(3, ("Session started\n"));
1180         return _MALI_OSK_ERR_OK;
1181
1182 err_time_line:
1183         mali_soft_job_system_destroy(session->soft_job_system);
1184 err_soft:
1185         mali_memory_session_end(session);
1186 err_session:
1187         mali_mmu_pagedir_free(session->page_directory);
1188 err_mmu:
1189         _mali_osk_notification_queue_term(session->ioctl_queue);
1190 err:
1191         _mali_osk_free(session);
1192         MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1193
1194 }
1195
1196 #if defined(DEBUG)
1197 /* parameter used for debug */
1198 extern u32 num_pm_runtime_resume;
1199 extern u32 num_pm_updates;
1200 extern u32 num_pm_updates_up;
1201 extern u32 num_pm_updates_down;
1202 #endif
1203
1204 _mali_osk_errcode_t _mali_ukk_close(void **context)
1205 {
1206         struct mali_session_data *session;
1207         MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS);
1208         session = (struct mali_session_data *)*context;
1209
1210         MALI_DEBUG_PRINT(3, ("Session ending\n"));
1211
1212         MALI_DEBUG_ASSERT_POINTER(session->soft_job_system);
1213         MALI_DEBUG_ASSERT_POINTER(session->timeline_system);
1214
1215         /* Remove session from list of all sessions. */
1216         mali_session_remove(session);
1217
1218         /* This flag is used to prevent queueing of jobs due to activation. */
1219         session->is_aborting = MALI_TRUE;
1220
1221         /* Stop the soft job timer. */
1222         mali_timeline_system_stop_timer(session->timeline_system);
1223
1224         /* Abort queued jobs */
1225         mali_scheduler_abort_session(session);
1226
1227         /* Abort executing jobs */
1228         mali_executor_abort_session(session);
1229
1230         /* Abort the soft job system. */
1231         mali_soft_job_system_abort(session->soft_job_system);
1232
1233         /* Force execution of all pending bottom half processing for GP and PP. */
1234         _mali_osk_wq_flush();
1235
1236         /* The session PP list should now be empty. */
1237         MALI_DEBUG_ASSERT(_mali_osk_list_empty(&session->pp_job_list));
1238
1239         /* At this point the GP and PP scheduler no longer has any jobs queued or running from this
1240          * session, and all soft jobs in the soft job system has been destroyed. */
1241
1242         /* Any trackers left in the timeline system are directly or indirectly waiting on external
1243          * sync fences.  Cancel all sync fence waiters to trigger activation of all remaining
1244          * trackers.  This call will sleep until all timelines are empty. */
1245         mali_timeline_system_abort(session->timeline_system);
1246
1247         /* Flush pending work.
1248          * Needed to make sure all bottom half processing related to this
1249          * session has been completed, before we free internal data structures.
1250          */
1251         _mali_osk_wq_flush();
1252
1253         /* Destroy timeline system. */
1254         mali_timeline_system_destroy(session->timeline_system);
1255         session->timeline_system = NULL;
1256
1257         /* Destroy soft system. */
1258         mali_soft_job_system_destroy(session->soft_job_system);
1259         session->soft_job_system = NULL;
1260
1261         MALI_DEBUG_CODE({
1262                 /* Check that the pp_job_fb_lookup_list array is empty. */
1263                 u32 i;
1264                 for (i = 0; i < MALI_PP_JOB_FB_LOOKUP_LIST_SIZE; ++i)
1265                 {
1266                         MALI_DEBUG_ASSERT(_mali_osk_list_empty(&session->pp_job_fb_lookup_list[i]));
1267                 }
1268         });
1269
1270         /* Free remaining memory allocated to this session */
1271         mali_memory_session_end(session);
1272
1273 #if defined(CONFIG_MALI_DVFS)
1274         _mali_osk_atomic_term(&session->number_of_window_jobs);
1275 #endif
1276
1277 #if defined(CONFIG_MALI400_PROFILING)
1278         _mali_osk_profiling_stop_sampling(session->pid);
1279 #endif
1280
1281         /* Free session data structures */
1282         mali_mmu_pagedir_unmap(session->page_directory, MALI_DLBU_VIRT_ADDR, _MALI_OSK_MALI_PAGE_SIZE);
1283         mali_mmu_pagedir_free(session->page_directory);
1284         _mali_osk_notification_queue_term(session->ioctl_queue);
1285         _mali_osk_free(session);
1286
1287         *context = NULL;
1288
1289         MALI_DEBUG_PRINT(3, ("Session has ended\n"));
1290
1291 #if defined(DEBUG)
1292         MALI_DEBUG_PRINT(3, ("Stats: # runtime resumes: %u\n", num_pm_runtime_resume));
1293         MALI_DEBUG_PRINT(3, ("       # PM updates: .... %u (up %u, down %u)\n", num_pm_updates, num_pm_updates_up, num_pm_updates_down));
1294
1295         num_pm_runtime_resume = 0;
1296         num_pm_updates = 0;
1297         num_pm_updates_up = 0;
1298         num_pm_updates_down = 0;
1299 #endif
1300
1301         return _MALI_OSK_ERR_OK;;
1302 }
1303
1304 #if MALI_STATE_TRACKING
1305 u32 _mali_kernel_core_dump_state(char *buf, u32 size)
1306 {
1307         int n = 0; /* Number of bytes written to buf */
1308
1309         n += mali_scheduler_dump_state(buf + n, size - n);
1310         n += mali_executor_dump_state(buf + n, size - n);
1311
1312         return n;
1313 }
1314 #endif