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