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