Merge tag 'lsk-v3.10-android-14.12'
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / linux / mali_kernel_linux.c
1 /**
2  * This confidential and proprietary software may be used only as
3  * authorised by a licensing agreement from ARM Limited
4  * (C) COPYRIGHT 2008-2014 ARM Limited
5  * ALL RIGHTS RESERVED
6  * The entire notice above must be reproduced on all authorised
7  * copies and copies may only be made to the extent permitted
8  * by a licensing agreement from ARM Limited.
9  */
10
11 /**
12  * @file mali_kernel_linux.c
13  * Implementation of the Linux device driver entrypoints
14  */
15 #include <linux/module.h>   /* kernel module definitions */
16 #include <linux/fs.h>       /* file system operations */
17 #include <linux/cdev.h>     /* character device definitions */
18 #include <linux/mm.h>       /* memory manager definitions */
19 #include <linux/mali/mali_utgard_ioctl.h>
20 #include <linux/version.h>
21 #include <linux/device.h>
22 #include "mali_kernel_license.h"
23 #include <linux/platform_device.h>
24 #include <linux/miscdevice.h>
25 #include <linux/bug.h>
26 #include <linux/mali/mali_utgard.h>
27 #include "mali_kernel_common.h"
28 #include "mali_session.h"
29 #include "mali_kernel_core.h"
30 #include "mali_osk.h"
31 #include "mali_kernel_linux.h"
32 #include "mali_ukk.h"
33 #include "mali_ukk_wrappers.h"
34 #include "mali_kernel_sysfs.h"
35 #include "mali_pm.h"
36 #include "mali_kernel_license.h"
37 #include "mali_memory.h"
38 #include "mali_memory_dma_buf.h"
39 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
40 #include "mali_profiling_internal.h"
41 #endif
42 #include <linux/of.h>
43
44 /* Streamline support for the Mali driver */
45 #if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_MALI400_PROFILING)
46 /* Ask Linux to create the tracepoints */
47 #define CREATE_TRACE_POINTS
48 #include "mali_linux_trace.h"
49
50 EXPORT_TRACEPOINT_SYMBOL_GPL(mali_timeline_event);
51 EXPORT_TRACEPOINT_SYMBOL_GPL(mali_hw_counter);
52 EXPORT_TRACEPOINT_SYMBOL_GPL(mali_sw_counters);
53 #endif /* CONFIG_TRACEPOINTS */
54
55 /* from the __malidrv_build_info.c file that is generated during build */
56 extern const char *__malidrv_build_info(void);
57
58 /* Module parameter to control log level */
59 int mali_debug_level = 2;
60 module_param(mali_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */
61 MODULE_PARM_DESC(mali_debug_level, "Higher number, more dmesg output");
62
63 extern int mali_max_job_runtime;
64 module_param(mali_max_job_runtime, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
65 MODULE_PARM_DESC(mali_max_job_runtime, "Maximum allowed job runtime in msecs.\nJobs will be killed after this no matter what");
66
67 extern int mali_l2_max_reads;
68 module_param(mali_l2_max_reads, int, S_IRUSR | S_IRGRP | S_IROTH);
69 MODULE_PARM_DESC(mali_l2_max_reads, "Maximum reads for Mali L2 cache");
70
71 extern unsigned int mali_dedicated_mem_start;
72 module_param(mali_dedicated_mem_start, uint, S_IRUSR | S_IRGRP | S_IROTH);
73 MODULE_PARM_DESC(mali_dedicated_mem_start, "Physical start address of dedicated Mali GPU memory.");
74
75 extern unsigned int mali_dedicated_mem_size;
76 module_param(mali_dedicated_mem_size, uint, S_IRUSR | S_IRGRP | S_IROTH);
77 MODULE_PARM_DESC(mali_dedicated_mem_size, "Size of dedicated Mali GPU memory.");
78
79 extern unsigned long mali_shared_mem_size;
80 module_param(mali_shared_mem_size, ulong, S_IRUSR | S_IRGRP | S_IROTH);
81 MODULE_PARM_DESC(mali_shared_mem_size, "Size of shared Mali GPU memory.");
82
83 #if defined(CONFIG_MALI400_PROFILING)
84 extern int mali_boot_profiling;
85 module_param(mali_boot_profiling, int, S_IRUSR | S_IRGRP | S_IROTH);
86 MODULE_PARM_DESC(mali_boot_profiling, "Start profiling as a part of Mali driver initialization");
87 #endif
88
89 extern int mali_max_pp_cores_group_1;
90 module_param(mali_max_pp_cores_group_1, int, S_IRUSR | S_IRGRP | S_IROTH);
91 MODULE_PARM_DESC(mali_max_pp_cores_group_1, "Limit the number of PP cores to use from first PP group.");
92
93 extern int mali_max_pp_cores_group_2;
94 module_param(mali_max_pp_cores_group_2, int, S_IRUSR | S_IRGRP | S_IROTH);
95 MODULE_PARM_DESC(mali_max_pp_cores_group_2, "Limit the number of PP cores to use from second PP group (Mali-450 only).");
96
97 #if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
98 /** the max fps the same as display vsync default 60, can set by module insert parameter */
99 extern int mali_max_system_fps;
100 module_param(mali_max_system_fps, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
101 MODULE_PARM_DESC(mali_max_system_fps, "Max system fps the same as display VSYNC.");
102
103 /** a lower limit on their desired FPS default 58, can set by module insert parameter*/
104 extern int mali_desired_fps;
105 module_param(mali_desired_fps, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
106 MODULE_PARM_DESC(mali_desired_fps, "A bit lower than max_system_fps which user desired fps");
107 #endif
108
109 #if MALI_ENABLE_CPU_CYCLES
110 #include <linux/cpumask.h>
111 #include <linux/timer.h>
112 #include <asm/smp.h>
113 static struct timer_list mali_init_cpu_clock_timers[8];
114 static u32 mali_cpu_clock_last_value[8] = {0,};
115 #endif
116
117 /* Export symbols from common code: mali_user_settings.c */
118 #include "mali_user_settings_db.h"
119 EXPORT_SYMBOL(mali_set_user_setting);
120 EXPORT_SYMBOL(mali_get_user_setting);
121
122 static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */
123
124 /* This driver only supports one Mali device, and this variable stores this single platform device */
125 struct platform_device *mali_platform_device = NULL;
126
127 /* This driver only supports one Mali device, and this variable stores the exposed misc device (/dev/mali) */
128 static struct miscdevice mali_miscdevice = { 0, };
129
130 static int mali_miscdevice_register(struct platform_device *pdev);
131 static void mali_miscdevice_unregister(void);
132
133 static int mali_open(struct inode *inode, struct file *filp);
134 static int mali_release(struct inode *inode, struct file *filp);
135 #ifdef HAVE_UNLOCKED_IOCTL
136 static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
137 #else
138 static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
139 #endif
140
141 static int mali_probe(struct platform_device *pdev);
142 static int mali_remove(struct platform_device *pdev);
143
144 static int mali_driver_suspend_scheduler(struct device *dev);
145 static int mali_driver_resume_scheduler(struct device *dev);
146
147 #ifdef CONFIG_PM_RUNTIME
148 static int mali_driver_runtime_suspend(struct device *dev);
149 static int mali_driver_runtime_resume(struct device *dev);
150 static int mali_driver_runtime_idle(struct device *dev);
151 #endif
152
153 #if defined(MALI_FAKE_PLATFORM_DEVICE)
154 extern int mali_platform_device_register(struct platform_device *pdev);
155 extern int mali_platform_device_unregister(struct platform_device *pdev);
156 #endif
157
158 /* Linux power management operations provided by the Mali device driver */
159 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29))
160 struct pm_ext_ops mali_dev_ext_pm_ops = {
161         .base =
162         {
163                 .suspend = mali_driver_suspend_scheduler,
164                 .resume = mali_driver_resume_scheduler,
165                 .freeze = mali_driver_suspend_scheduler,
166                 .thaw =   mali_driver_resume_scheduler,
167         },
168 };
169 #else
170 static const struct dev_pm_ops mali_dev_pm_ops = {
171 #ifdef CONFIG_PM_RUNTIME
172         .runtime_suspend = mali_driver_runtime_suspend,
173         .runtime_resume = mali_driver_runtime_resume,
174         .runtime_idle = mali_driver_runtime_idle,
175 #endif
176         .suspend = mali_driver_suspend_scheduler,
177         .resume = mali_driver_resume_scheduler,
178         .freeze = mali_driver_suspend_scheduler,
179         .thaw = mali_driver_resume_scheduler,
180         .poweroff = mali_driver_suspend_scheduler,
181 };
182 #endif
183
184 #ifdef CONFIG_OF
185 static const struct of_device_id mali_dt_ids[] = {
186         { .compatible = "arm,mali400" },
187         { /* sentinel */ }
188 };
189 MODULE_DEVICE_TABLE(of, mali_dt_ids);
190 #endif
191
192 /* The Mali device driver struct */
193 static struct platform_driver mali_platform_driver = {
194         .probe  = mali_probe,
195         .remove = mali_remove,
196 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29))
197         .pm = &mali_dev_ext_pm_ops,
198 #endif
199         .driver =
200         {
201                 .name   = MALI_GPU_NAME_UTGARD,
202                 .owner  = THIS_MODULE,
203                 .bus = &platform_bus_type,
204 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
205                 .pm = &mali_dev_pm_ops,
206                 .of_match_table = of_match_ptr(mali_dt_ids),
207 #endif
208         },
209 };
210
211 /* Linux misc device operations (/dev/mali) */
212 struct file_operations mali_fops = {
213         .owner = THIS_MODULE,
214         .open = mali_open,
215         .release = mali_release,
216 #ifdef HAVE_UNLOCKED_IOCTL
217         .unlocked_ioctl = mali_ioctl,
218 #else
219         .ioctl = mali_ioctl,
220 #endif
221         .compat_ioctl = mali_ioctl,
222         .mmap = mali_mmap
223 };
224
225
226 #if MALI_ENABLE_CPU_CYCLES
227 void mali_init_cpu_time_counters(int reset, int enable_divide_by_64)
228 {
229         /* The CPU assembly reference used is: ARM Architecture Reference Manual ARMv7-AR C.b */
230         u32 write_value;
231
232         /* See B4.1.116 PMCNTENSET, Performance Monitors Count Enable Set register, VMSA */
233         /* setting p15 c9 c12 1 to 0x8000000f==CPU_CYCLE_ENABLE |EVENT_3_ENABLE|EVENT_2_ENABLE|EVENT_1_ENABLE|EVENT_0_ENABLE */
234         asm volatile("mcr p15, 0, %0, c9, c12, 1" :: "r"(0x8000000f));
235
236
237         /* See B4.1.117 PMCR, Performance Monitors Control Register. Writing to p15, c9, c12, 0 */
238         write_value = 1 << 0; /* Bit 0 set. Enable counters */
239         if (reset) {
240                 write_value |= 1 << 1; /* Reset event counters */
241                 write_value |= 1 << 2; /* Reset cycle counter  */
242         }
243         if (enable_divide_by_64) {
244                 write_value |= 1 << 3; /* Enable the Clock divider by 64 */
245         }
246         write_value |= 1 << 4; /* Export enable. Not needed */
247         asm volatile("MCR p15, 0, %0, c9, c12, 0\t\n" :: "r"(write_value));
248
249         /* PMOVSR Overflow Flag Status Register - Clear Clock and Event overflows */
250         asm volatile("MCR p15, 0, %0, c9, c12, 3\t\n" :: "r"(0x8000000f));
251
252
253         /* See B4.1.124 PMUSERENR - setting p15 c9 c14 to 1" */
254         /* User mode access to the Performance Monitors enabled. */
255         /* Lets User space read cpu clock cycles */
256         asm volatile("mcr p15, 0, %0, c9, c14, 0" :: "r"(1));
257 }
258
259 /** A timer function that configures the cycle clock counter on current CPU.
260  * The function \a mali_init_cpu_time_counters_on_all_cpus sets up this
261  * function to trigger on all Cpus during module load.
262  */
263 static void mali_init_cpu_clock_timer_func(unsigned long data)
264 {
265         int reset_counters, enable_divide_clock_counter_by_64;
266         int current_cpu = raw_smp_processor_id();
267         unsigned int sample0;
268         unsigned int sample1;
269
270         MALI_IGNORE(data);
271
272         reset_counters = 1;
273         enable_divide_clock_counter_by_64 = 0;
274         mali_init_cpu_time_counters(reset_counters, enable_divide_clock_counter_by_64);
275
276         sample0 = mali_get_cpu_cyclecount();
277         sample1 = mali_get_cpu_cyclecount();
278
279         MALI_DEBUG_PRINT(3, ("Init Cpu %d cycle counter- First two samples: %08x %08x \n", current_cpu, sample0, sample1));
280 }
281
282 /** A timer functions for storing current time on all cpus.
283  * Used for checking if the clocks have similar values or if they are drifting.
284  */
285 static void mali_print_cpu_clock_timer_func(unsigned long data)
286 {
287         int current_cpu = raw_smp_processor_id();
288         unsigned int sample0;
289
290         MALI_IGNORE(data);
291         sample0 = mali_get_cpu_cyclecount();
292         if (current_cpu < 8) {
293                 mali_cpu_clock_last_value[current_cpu] = sample0;
294         }
295 }
296
297 /** Init the performance registers on all CPUs to count clock cycles.
298  * For init \a print_only should be 0.
299  * If \a print_only is 1, it will intead print the current clock value of all CPUs.
300  */
301 void mali_init_cpu_time_counters_on_all_cpus(int print_only)
302 {
303         int i = 0;
304         int cpu_number;
305         int jiffies_trigger;
306         int jiffies_wait;
307
308         jiffies_wait = 2;
309         jiffies_trigger = jiffies + jiffies_wait;
310
311         for (i = 0 ; i < 8 ; i++) {
312                 init_timer(&mali_init_cpu_clock_timers[i]);
313                 if (print_only) mali_init_cpu_clock_timers[i].function = mali_print_cpu_clock_timer_func;
314                 else            mali_init_cpu_clock_timers[i].function = mali_init_cpu_clock_timer_func;
315                 mali_init_cpu_clock_timers[i].expires = jiffies_trigger ;
316         }
317         cpu_number = cpumask_first(cpu_online_mask);
318         for (i = 0 ; i < 8 ; i++) {
319                 int next_cpu;
320                 add_timer_on(&mali_init_cpu_clock_timers[i], cpu_number);
321                 next_cpu = cpumask_next(cpu_number, cpu_online_mask);
322                 if (next_cpu >= nr_cpu_ids) break;
323                 cpu_number = next_cpu;
324         }
325
326         while (jiffies_wait) jiffies_wait = schedule_timeout_uninterruptible(jiffies_wait);
327
328         for (i = 0 ; i < 8 ; i++) {
329                 del_timer_sync(&mali_init_cpu_clock_timers[i]);
330         }
331
332         if (print_only) {
333                 if ((0 == mali_cpu_clock_last_value[2]) && (0 == mali_cpu_clock_last_value[3])) {
334                         /* Diff can be printed if we want to check if the clocks are in sync
335                         int diff = mali_cpu_clock_last_value[0] - mali_cpu_clock_last_value[1];*/
336                         MALI_DEBUG_PRINT(2, ("CPU cycle counters readout all: %08x %08x\n", mali_cpu_clock_last_value[0], mali_cpu_clock_last_value[1]));
337                 } else {
338                         MALI_DEBUG_PRINT(2, ("CPU cycle counters readout all: %08x %08x %08x %08x\n", mali_cpu_clock_last_value[0], mali_cpu_clock_last_value[1], mali_cpu_clock_last_value[2], mali_cpu_clock_last_value[3]));
339                 }
340         }
341 }
342 #endif
343
344
345 int mali_module_init(void)
346 {
347         int err = 0;
348
349         MALI_DEBUG_PRINT(2, ("Inserting Mali v%d device driver. \n", _MALI_API_VERSION));
350         MALI_DEBUG_PRINT(2, ("Compiled: %s, time: %s.\n", __DATE__, __TIME__));
351         MALI_DEBUG_PRINT(2, ("Driver revision: %s\n", SVN_REV_STRING));
352
353 #if MALI_ENABLE_CPU_CYCLES
354         mali_init_cpu_time_counters_on_all_cpus(0);
355         MALI_DEBUG_PRINT(2, ("CPU cycle counter setup complete\n"));
356         /* Printing the current cpu counters */
357         mali_init_cpu_time_counters_on_all_cpus(1);
358 #endif
359
360         MALI_PRINT(("mali_module_init() registering driver\n"));
361
362         err = platform_driver_register(&mali_platform_driver);
363
364         if (0 != err) {
365                 MALI_PRINT(("mali_module_init() Failed to register driver (%d)\n", err));
366                 mali_platform_device = NULL;
367                 return err;
368         }
369
370 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
371         err = _mali_internal_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE);
372         if (0 != err) {
373                 /* No biggie if we wheren't able to initialize the profiling */
374                 MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n"));
375         }
376 #endif
377
378         MALI_PRINT(("Mali device driver loaded\n"));
379
380         return 0; /* Success */
381 }
382
383 void mali_module_exit(void)
384 {
385         MALI_DEBUG_PRINT(2, ("Unloading Mali v%d device driver.\n", _MALI_API_VERSION));
386
387         MALI_DEBUG_PRINT(2, ("mali_module_exit() unregistering driver\n"));
388
389 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
390         _mali_internal_profiling_term();
391 #endif
392
393         platform_driver_unregister(&mali_platform_driver);
394
395 #if defined(MALI_FAKE_PLATFORM_DEVICE)
396         MALI_DEBUG_PRINT(2, ("mali_module_exit() unregistering device\n"));
397         mali_platform_device_unregister(mali_platform_device);
398 #endif
399
400         MALI_PRINT(("Mali device driver unloaded\n"));
401 }
402
403 static int mali_probe(struct platform_device *pdev)
404 {
405         int err;
406
407         MALI_DEBUG_PRINT(2, ("mali_probe(): Called for platform device %s\n", pdev->name));
408
409         if (NULL != mali_platform_device) {
410                 /* Already connected to a device, return error */
411                 MALI_PRINT_ERROR(("mali_probe(): The Mali driver is already connected with a Mali device."));
412                 return -EEXIST;
413         }
414
415         mali_platform_device = pdev;
416
417         pr_info("mali_platform_device->num_resources = %d\n",mali_platform_device->num_resources);
418
419         {
420                 int i = 0;
421                 for(i=0;i<mali_platform_device->num_resources;i++)
422                 {
423                         pr_info("mali_platform_device->resource[%d].start = 0x%08x\n",i,mali_platform_device->resource[i].start);
424                 }
425         }
426         
427         
428 #if defined(MALI_FAKE_PLATFORM_DEVICE)
429         MALI_DEBUG_PRINT(2, ("mali_module_init() registering device\n"));
430         err = mali_platform_device_register(mali_platform_device);
431         if (0 != err) 
432         {
433                 mali_platform_device_unregister(mali_platform_device);
434                 return err;
435         }
436 #endif
437
438         if (_MALI_OSK_ERR_OK == _mali_osk_wq_init()) {
439                 /* Initialize the Mali GPU HW specified by pdev */
440                 if (_MALI_OSK_ERR_OK == mali_initialize_subsystems()) {
441                         /* Register a misc device (so we are accessible from user space) */
442                         err = mali_miscdevice_register(pdev);
443                         if (0 == err) {
444                                 /* Setup sysfs entries */
445                                 err = mali_sysfs_register(mali_dev_name);
446                                 if (0 == err) {
447                                         MALI_DEBUG_PRINT(2, ("mali_probe(): Successfully initialized driver for platform device %s\n", pdev->name));
448                                         return 0;
449                                 } else {
450                                         MALI_PRINT_ERROR(("mali_probe(): failed to register sysfs entries"));
451                                 }
452                                 mali_miscdevice_unregister();
453                         } else {
454                                 MALI_PRINT_ERROR(("mali_probe(): failed to register Mali misc device."));
455                         }
456                         mali_terminate_subsystems();
457                 } else {
458                         MALI_PRINT_ERROR(("mali_probe(): Failed to initialize Mali device driver."));
459                 }
460                 _mali_osk_wq_term();
461         }
462
463         mali_platform_device = NULL;
464         return -EFAULT;
465 }
466
467 static int mali_remove(struct platform_device *pdev)
468 {
469         MALI_DEBUG_PRINT(2, ("mali_remove() called for platform device %s\n", pdev->name));
470         mali_sysfs_unregister();
471         mali_miscdevice_unregister();
472         mali_terminate_subsystems();
473         _mali_osk_wq_term();
474         mali_platform_device = NULL;
475         return 0;
476 }
477
478 static int mali_miscdevice_register(struct platform_device *pdev)
479 {
480         int err;
481
482         mali_miscdevice.minor = MISC_DYNAMIC_MINOR;
483         mali_miscdevice.name = mali_dev_name;
484         mali_miscdevice.fops = &mali_fops;
485         mali_miscdevice.parent = get_device(&pdev->dev);
486
487         err = misc_register(&mali_miscdevice);
488         if (0 != err) {
489                 MALI_PRINT_ERROR(("Failed to register misc device, misc_register() returned %d\n", err));
490         }
491
492         return err;
493 }
494
495 static void mali_miscdevice_unregister(void)
496 {
497         misc_deregister(&mali_miscdevice);
498 }
499
500 static int mali_driver_suspend_scheduler(struct device *dev)
501 {
502         mali_pm_os_suspend();
503         return 0;
504 }
505
506 static int mali_driver_resume_scheduler(struct device *dev)
507 {
508         mali_pm_os_resume();
509         return 0;
510 }
511
512 #ifdef CONFIG_PM_RUNTIME
513 static int mali_driver_runtime_suspend(struct device *dev)
514 {
515         mali_pm_runtime_suspend();
516         return 0;
517 }
518
519 static int mali_driver_runtime_resume(struct device *dev)
520 {
521         mali_pm_runtime_resume();
522         return 0;
523 }
524
525 static int mali_driver_runtime_idle(struct device *dev)
526 {
527         /* Nothing to do */
528         return 0;
529 }
530 #endif
531
532 static int mali_open(struct inode *inode, struct file *filp)
533 {
534         struct mali_session_data *session_data;
535         _mali_osk_errcode_t err;
536
537         /* input validation */
538         if (mali_miscdevice.minor != iminor(inode)) {
539                 MALI_PRINT_ERROR(("mali_open() Minor does not match\n"));
540                 return -ENODEV;
541         }
542
543         /* allocated struct to track this session */
544         err = _mali_ukk_open((void **)&session_data);
545         if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
546
547         /* initialize file pointer */
548         filp->f_pos = 0;
549
550         /* link in our session data */
551         filp->private_data = (void *)session_data;
552
553         return 0;
554 }
555
556 static int mali_release(struct inode *inode, struct file *filp)
557 {
558         _mali_osk_errcode_t err;
559
560         /* input validation */
561         if (mali_miscdevice.minor != iminor(inode)) {
562                 MALI_PRINT_ERROR(("mali_release() Minor does not match\n"));
563                 return -ENODEV;
564         }
565
566         err = _mali_ukk_close((void **)&filp->private_data);
567         if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
568
569         return 0;
570 }
571
572 int map_errcode(_mali_osk_errcode_t err)
573 {
574         switch (err) {
575         case _MALI_OSK_ERR_OK :
576                 return 0;
577         case _MALI_OSK_ERR_FAULT:
578                 return -EFAULT;
579         case _MALI_OSK_ERR_INVALID_FUNC:
580                 return -ENOTTY;
581         case _MALI_OSK_ERR_INVALID_ARGS:
582                 return -EINVAL;
583         case _MALI_OSK_ERR_NOMEM:
584                 return -ENOMEM;
585         case _MALI_OSK_ERR_TIMEOUT:
586                 return -ETIMEDOUT;
587         case _MALI_OSK_ERR_RESTARTSYSCALL:
588                 return -ERESTARTSYS;
589         case _MALI_OSK_ERR_ITEM_NOT_FOUND:
590                 return -ENOENT;
591         default:
592                 return -EFAULT;
593         }
594 }
595
596 #ifdef HAVE_UNLOCKED_IOCTL
597 static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
598 #else
599 static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
600 #endif
601 {
602         int err;
603         struct mali_session_data *session_data;
604
605 #ifndef HAVE_UNLOCKED_IOCTL
606         /* inode not used */
607         (void)inode;
608 #endif
609
610         MALI_DEBUG_PRINT(7, ("Ioctl received 0x%08X 0x%08lX\n", cmd, arg));
611
612         session_data = (struct mali_session_data *)filp->private_data;
613         if (NULL == session_data) {
614                 MALI_DEBUG_PRINT(7, ("filp->private_data was NULL\n"));
615                 return -ENOTTY;
616         }
617
618         if (NULL == (void *)arg) {
619                 MALI_DEBUG_PRINT(7, ("arg was NULL\n"));
620                 return -ENOTTY;
621         }
622
623         switch (cmd) {
624         case MALI_IOC_WAIT_FOR_NOTIFICATION:
625                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_wait_for_notification_s), sizeof(u64)));
626                 err = wait_for_notification_wrapper(session_data, (_mali_uk_wait_for_notification_s __user *)arg);
627                 break;
628
629         case MALI_IOC_GET_API_VERSION_V2:
630                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_get_api_version_v2_s), sizeof(u64)));
631                 err = get_api_version_v2_wrapper(session_data, (_mali_uk_get_api_version_v2_s __user *)arg);
632                 break;
633
634         case MALI_IOC_GET_API_VERSION:
635                 err = get_api_version_wrapper(session_data, (_mali_uk_get_api_version_s __user *)arg);
636                 break;
637
638         case MALI_IOC_POST_NOTIFICATION:
639                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_post_notification_s), sizeof(u64)));
640                 err = post_notification_wrapper(session_data, (_mali_uk_post_notification_s __user *)arg);
641                 break;
642
643         case MALI_IOC_GET_MALI_VERSION_IN_RK30:
644                 err = get_mali_version_in_rk30_wrapper(session_data,(_mali_uk_get_mali_version_in_rk30_s __user *)arg);
645                 break;
646                 
647         case MALI_IOC_GET_USER_SETTINGS:
648                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_get_user_settings_s), sizeof(u64)));
649                 err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg);
650                 break;
651
652         case MALI_IOC_REQUEST_HIGH_PRIORITY:
653                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_request_high_priority_s), sizeof(u64)));
654                 err = request_high_priority_wrapper(session_data, (_mali_uk_request_high_priority_s __user *)arg);
655                 break;
656
657 #if defined(CONFIG_MALI400_PROFILING)
658         case MALI_IOC_PROFILING_ADD_EVENT:
659                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_profiling_add_event_s), sizeof(u64)));
660                 err = profiling_add_event_wrapper(session_data, (_mali_uk_profiling_add_event_s __user *)arg);
661                 break;
662
663         case MALI_IOC_PROFILING_REPORT_SW_COUNTERS:
664                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_sw_counters_report_s), sizeof(u64)));
665                 err = profiling_report_sw_counters_wrapper(session_data, (_mali_uk_sw_counters_report_s __user *)arg);
666                 break;
667
668
669         case MALI_IOC_PROFILING_MEMORY_USAGE_GET:
670                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_profiling_memory_usage_get_s), sizeof(u64)));
671                 err = profiling_memory_usage_get_wrapper(session_data, (_mali_uk_profiling_memory_usage_get_s __user *)arg);
672                 break;
673
674 #else
675
676         case MALI_IOC_PROFILING_ADD_EVENT:          /* FALL-THROUGH */
677         case MALI_IOC_PROFILING_REPORT_SW_COUNTERS: /* FALL-THROUGH */
678         case MALI_IOC_PROFILING_MEMORY_USAGE_GET:   /* FALL-THROUGH */
679                 MALI_DEBUG_PRINT(2, ("Profiling not supported\n"));
680                 err = -ENOTTY;
681                 break;
682
683 #endif
684
685         case MALI_IOC_MEM_WRITE_SAFE:
686                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_mem_write_safe_s), sizeof(u64)));
687                 err = mem_write_safe_wrapper(session_data, (_mali_uk_mem_write_safe_s __user *)arg);
688                 break;
689
690         case MALI_IOC_MEM_MAP_EXT:
691                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_map_external_mem_s), sizeof(u64)));
692                 err = mem_map_ext_wrapper(session_data, (_mali_uk_map_external_mem_s __user *)arg);
693                 break;
694
695         case MALI_IOC_MEM_UNMAP_EXT:
696                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_unmap_external_mem_s), sizeof(u64)));
697                 err = mem_unmap_ext_wrapper(session_data, (_mali_uk_unmap_external_mem_s __user *)arg);
698                 break;
699
700         case MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE:
701                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_query_mmu_page_table_dump_size_s), sizeof(u64)));
702                 err = mem_query_mmu_page_table_dump_size_wrapper(session_data, (_mali_uk_query_mmu_page_table_dump_size_s __user *)arg);
703                 break;
704
705         case MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE:
706                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_dump_mmu_page_table_s), sizeof(u64)));
707                 err = mem_dump_mmu_page_table_wrapper(session_data, (_mali_uk_dump_mmu_page_table_s __user *)arg);
708                 break;
709
710 #if defined(CONFIG_MALI400_UMP)
711
712         case MALI_IOC_MEM_ATTACH_UMP:
713                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_attach_ump_mem_s), sizeof(u64)));
714                 err = mem_attach_ump_wrapper(session_data, (_mali_uk_attach_ump_mem_s __user *)arg);
715                 break;
716
717         case MALI_IOC_MEM_RELEASE_UMP:
718                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_release_ump_mem_s), sizeof(u64)));
719                 err = mem_release_ump_wrapper(session_data, (_mali_uk_release_ump_mem_s __user *)arg);
720                 break;
721
722 #else
723
724         case MALI_IOC_MEM_ATTACH_UMP:
725         case MALI_IOC_MEM_RELEASE_UMP: /* FALL-THROUGH */
726                 MALI_DEBUG_PRINT(2, ("UMP not supported\n"));
727                 err = -ENOTTY;
728                 break;
729 #endif
730
731 #ifdef CONFIG_DMA_SHARED_BUFFER
732         case MALI_IOC_MEM_ATTACH_DMA_BUF:
733                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_attach_dma_buf_s), sizeof(u64)));
734                 err = mali_attach_dma_buf(session_data, (_mali_uk_attach_dma_buf_s __user *)arg);
735                 break;
736
737         case MALI_IOC_MEM_RELEASE_DMA_BUF:
738                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_release_dma_buf_s), sizeof(u64)));
739                 err = mali_release_dma_buf(session_data, (_mali_uk_release_dma_buf_s __user *)arg);
740                 break;
741
742         case MALI_IOC_MEM_DMA_BUF_GET_SIZE:
743                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_dma_buf_get_size_s), sizeof(u64)));
744                 err = mali_dma_buf_get_size(session_data, (_mali_uk_dma_buf_get_size_s __user *)arg);
745                 break;
746 #else
747
748         case MALI_IOC_MEM_ATTACH_DMA_BUF:   /* FALL-THROUGH */
749         case MALI_IOC_MEM_RELEASE_DMA_BUF:  /* FALL-THROUGH */
750         case MALI_IOC_MEM_DMA_BUF_GET_SIZE: /* FALL-THROUGH */
751                 MALI_DEBUG_PRINT(2, ("DMA-BUF not supported\n"));
752                 err = -ENOTTY;
753                 break;
754 #endif
755
756         case MALI_IOC_PP_START_JOB:
757                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_pp_start_job_s), sizeof(u64)));
758                 err = pp_start_job_wrapper(session_data, (_mali_uk_pp_start_job_s __user *)arg);
759                 break;
760
761         case MALI_IOC_PP_AND_GP_START_JOB:
762                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_pp_and_gp_start_job_s), sizeof(u64)));
763                 err = pp_and_gp_start_job_wrapper(session_data, (_mali_uk_pp_and_gp_start_job_s __user *)arg);
764                 break;
765
766         case MALI_IOC_PP_NUMBER_OF_CORES_GET:
767                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_get_pp_number_of_cores_s), sizeof(u64)));
768                 err = pp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_pp_number_of_cores_s __user *)arg);
769                 break;
770
771         case MALI_IOC_PP_CORE_VERSION_GET:
772                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_get_pp_core_version_s), sizeof(u64)));
773                 err = pp_get_core_version_wrapper(session_data, (_mali_uk_get_pp_core_version_s __user *)arg);
774                 break;
775
776         case MALI_IOC_PP_DISABLE_WB:
777                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_pp_disable_wb_s), sizeof(u64)));
778                 err = pp_disable_wb_wrapper(session_data, (_mali_uk_pp_disable_wb_s __user *)arg);
779                 break;
780
781         case MALI_IOC_GP2_START_JOB:
782                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_gp_start_job_s), sizeof(u64)));
783                 err = gp_start_job_wrapper(session_data, (_mali_uk_gp_start_job_s __user *)arg);
784                 break;
785
786         case MALI_IOC_GP2_NUMBER_OF_CORES_GET:
787                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_get_gp_number_of_cores_s), sizeof(u64)));
788                 err = gp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_gp_number_of_cores_s __user *)arg);
789                 break;
790
791         case MALI_IOC_GP2_CORE_VERSION_GET:
792                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_get_gp_core_version_s), sizeof(u64)));
793                 err = gp_get_core_version_wrapper(session_data, (_mali_uk_get_gp_core_version_s __user *)arg);
794                 break;
795
796         case MALI_IOC_GP2_SUSPEND_RESPONSE:
797                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_gp_suspend_response_s), sizeof(u64)));
798                 err = gp_suspend_response_wrapper(session_data, (_mali_uk_gp_suspend_response_s __user *)arg);
799                 break;
800
801         case MALI_IOC_VSYNC_EVENT_REPORT:
802                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_vsync_event_report_s), sizeof(u64)));
803                 err = vsync_event_report_wrapper(session_data, (_mali_uk_vsync_event_report_s __user *)arg);
804                 break;
805
806         case MALI_IOC_TIMELINE_GET_LATEST_POINT:
807                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_timeline_get_latest_point_s), sizeof(u64)));
808                 err = timeline_get_latest_point_wrapper(session_data, (_mali_uk_timeline_get_latest_point_s __user *)arg);
809                 break;
810         case MALI_IOC_TIMELINE_WAIT:
811                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_timeline_wait_s), sizeof(u64)));
812                 err = timeline_wait_wrapper(session_data, (_mali_uk_timeline_wait_s __user *)arg);
813                 break;
814         case MALI_IOC_TIMELINE_CREATE_SYNC_FENCE:
815                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_timeline_create_sync_fence_s), sizeof(u64)));
816                 err = timeline_create_sync_fence_wrapper(session_data, (_mali_uk_timeline_create_sync_fence_s __user *)arg);
817                 break;
818         case MALI_IOC_SOFT_JOB_START:
819                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_soft_job_start_s), sizeof(u64)));
820                 err = soft_job_start_wrapper(session_data, (_mali_uk_soft_job_start_s __user *)arg);
821                 break;
822         case MALI_IOC_SOFT_JOB_SIGNAL:
823                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_soft_job_signal_s), sizeof(u64)));
824                 err = soft_job_signal_wrapper(session_data, (_mali_uk_soft_job_signal_s __user *)arg);
825                 break;
826
827         default:
828                 MALI_DEBUG_PRINT(2, ("No handler for ioctl 0x%08X 0x%08lX\n", cmd, arg));
829                 err = -ENOTTY;
830         };
831
832         return err;
833 }
834
835
836 module_init(mali_module_init);
837 module_exit(mali_module_exit);
838
839 MODULE_LICENSE(MALI_KERNEL_LINUX_LICENSE);
840 MODULE_AUTHOR("ARM Ltd.");
841 MODULE_VERSION(SVN_REV_STRING);