ARM64: DTS: Add rk3399-firefly uart4 device, node as /dev/ttyS1
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / umplock / umplock_driver.c
1 /*
2  * Copyright (C) 2012-2016 ARM Limited. All rights reserved.
3  * 
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  * 
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
9  */
10
11 #include <linux/init.h>
12 #include <linux/module.h>
13 #include <linux/fs.h>
14 #include <linux/slab.h>
15 #include <linux/cdev.h>
16 #include <linux/device.h>
17 #include <asm/uaccess.h>
18 #include "umplock_ioctl.h"
19 #include <linux/sched.h>
20
21 #define MAX_ITEMS 1024
22 #define MAX_PIDS 128
23
24 typedef struct lock_cmd_priv {
25         uint32_t msg[128];    /*ioctl args*/
26         u32 pid;              /*process id*/
27 } _lock_cmd_priv;
28
29 typedef struct lock_ref {
30         int ref_count;
31         u32 pid;
32         u32 down_count;
33 } _lock_ref;
34
35 typedef struct umplock_item {
36         u32 secure_id;
37         u32 id_ref_count;
38         u32 owner;
39         _lock_access_usage usage;
40         _lock_ref references[MAX_PIDS];
41         struct semaphore item_lock;
42 } umplock_item;
43
44 typedef struct umplock_device_private {
45         struct mutex item_list_lock;
46         atomic_t sessions;
47         umplock_item items[MAX_ITEMS];
48         u32 pids[MAX_PIDS];
49 } umplock_device_private;
50
51 struct umplock_device {
52         struct cdev cdev;
53         struct class *umplock_class;
54 };
55
56 static struct umplock_device umplock_device;
57 static umplock_device_private device;
58 static dev_t umplock_dev;
59 static char umplock_dev_name[] = "umplock";
60
61 int umplock_debug_level = 0;
62 module_param(umplock_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */
63 MODULE_PARM_DESC(umplock_debug_level, "set umplock_debug_level to print debug messages");
64
65 #define PDEBUG(level, fmt, args...) do { if ((level) <= umplock_debug_level) printk(KERN_DEBUG "umplock: " fmt, ##args); } while (0)
66 #define PERROR(fmt, args...) do { printk(KERN_ERR "umplock: " fmt, ##args); } while (0)
67
68 int umplock_find_item(u32 secure_id)
69 {
70         int i;
71         for (i = 0; i < MAX_ITEMS; i++) {
72                 if (device.items[i].secure_id == secure_id) {
73                         return i;
74                 }
75         }
76
77         return -1;
78 }
79
80 static int umplock_find_item_by_pid(_lock_cmd_priv *lock_cmd, int *item_slot, int *ref_slot)
81 {
82         _lock_item_s *lock_item;
83         int i, j;
84
85         lock_item = (_lock_item_s *)&lock_cmd->msg;
86
87         i = umplock_find_item(lock_item->secure_id);
88
89         if (i < 0) {
90                 return -1;
91         }
92
93         for (j = 0; j < MAX_PIDS; j++) {
94                 if (device.items[i].references[j].pid == lock_cmd->pid) {
95                         *item_slot = i;
96                         *ref_slot = j;
97                         return 0;
98                 }
99         }
100         return -1 ;
101 }
102
103 static int umplock_find_client_valid(u32 pid)
104 {
105         int i;
106
107         if (pid == 0) {
108                 return -1;
109         }
110
111         for (i = 0; i < MAX_PIDS; i++) {
112                 if (device.pids[i] == pid) {
113                         return i;
114                 }
115         }
116
117         return -1;
118 }
119
120 static int do_umplock_create_locked(_lock_cmd_priv *lock_cmd)
121 {
122         int i_index, ref_index;
123         int ret;
124         _lock_item_s *lock_item = (_lock_item_s *)&lock_cmd->msg;
125
126         i_index = ref_index = -1;
127
128         ret = umplock_find_client_valid(lock_cmd->pid);
129         if (ret < 0) {
130                 /*lock request from an invalid client pid, do nothing*/
131                 return -EINVAL;
132         }
133
134         ret = umplock_find_item_by_pid(lock_cmd, &i_index, &ref_index);
135         if (ret >= 0) {
136         } else if ((i_index = umplock_find_item(lock_item->secure_id)) >= 0) {
137                 for (ref_index = 0; ref_index < MAX_PIDS; ref_index++) {
138                         if (device.items[i_index].references[ref_index].pid == 0) {
139                                 break;
140                         }
141                 }
142                 if (ref_index < MAX_PIDS) {
143                         device.items[i_index].references[ref_index].pid = lock_cmd->pid;
144                         device.items[i_index].references[ref_index].ref_count = 0;
145                         device.items[i_index].references[ref_index].down_count = 0;
146                 } else {
147                         PERROR("whoops, item ran out of available reference slots\n");
148                         return -EINVAL;
149
150                 }
151         } else {
152                 i_index = umplock_find_item(0);
153
154                 if (i_index >= 0) {
155                         device.items[i_index].secure_id = lock_item->secure_id;
156                         device.items[i_index].id_ref_count = 0;
157                         device.items[i_index].usage = lock_item->usage;
158                         device.items[i_index].references[0].pid = lock_cmd->pid;
159                         device.items[i_index].references[0].ref_count = 0;
160                         device.items[i_index].references[0].down_count = 0;
161                         sema_init(&device.items[i_index].item_lock, 1);
162                 } else {
163                         PERROR("whoops, ran out of available slots\n");
164                         return -EINVAL;
165                 }
166         }
167
168         return 0;
169 }
170 /** IOCTLs **/
171
172 static int do_umplock_create(_lock_cmd_priv *lock_cmd)
173 {
174         return 0;
175 }
176
177 static int do_umplock_process(_lock_cmd_priv *lock_cmd)
178 {
179         int ret, i_index, ref_index;
180         _lock_item_s *lock_item = (_lock_item_s *)&lock_cmd->msg;
181
182         mutex_lock(&device.item_list_lock);
183
184         if (0 == lock_item->secure_id) {
185                 PERROR("IOCTL_UMPLOCK_PROCESS called with secure_id is 0, pid: %d\n", lock_cmd->pid);
186                 mutex_unlock(&device.item_list_lock);
187                 return -EINVAL;
188         }
189
190         ret = do_umplock_create_locked(lock_cmd);
191         if (ret < 0) {
192                 mutex_unlock(&device.item_list_lock);
193                 return -EINVAL;
194         }
195
196         ret = umplock_find_item_by_pid(lock_cmd, &i_index, &ref_index);
197         if (ret < 0) {
198                 /*fail to find a item*/
199                 PERROR("IOCTL_UMPLOCK_PROCESS called with invalid parameter, pid: %d\n", lock_cmd->pid);
200                 mutex_unlock(&device.item_list_lock);
201                 return -EINVAL;
202         }
203         device.items[i_index].references[ref_index].ref_count++;
204         device.items[i_index].id_ref_count++;
205         PDEBUG(1, "try to lock, pid: %d, secure_id: 0x%x, ref_count: %d\n", lock_cmd->pid, lock_item->secure_id, device.items[i_index].references[ref_index].ref_count);
206
207         if (lock_cmd->pid == device.items[i_index].owner) {
208                 PDEBUG(1, "already own the lock, pid: %d, secure_id: 0x%x, ref_count: %d\n", lock_cmd->pid, lock_item->secure_id, device.items[i_index].references[ref_index].ref_count);
209                 mutex_unlock(&device.item_list_lock);
210                 return 0;
211         }
212
213         device.items[i_index].references[ref_index].down_count++;
214         mutex_unlock(&device.item_list_lock);
215         if (down_interruptible(&device.items[i_index].item_lock)) {
216                 /*wait up without hold the umplock. restore previous state and return*/
217                 mutex_lock(&device.item_list_lock);
218                 device.items[i_index].references[ref_index].ref_count--;
219                 device.items[i_index].id_ref_count--;
220                 device.items[i_index].references[ref_index].down_count--;
221                 if (0 == device.items[i_index].references[ref_index].ref_count) {
222                         device.items[i_index].references[ref_index].pid = 0;
223                         if (0 == device.items[i_index].id_ref_count) {
224                                 PDEBUG(1, "release item, pid: %d, secure_id: 0x%x\n", lock_cmd->pid, lock_item->secure_id);
225                                 device.items[i_index].secure_id = 0;
226                         }
227                 }
228
229                 PERROR("failed lock, pid: %d, secure_id: 0x%x, ref_count: %d\n", lock_cmd->pid, lock_item->secure_id, device.items[i_index].references[ref_index].ref_count);
230
231                 mutex_unlock(&device.item_list_lock);
232                 return -ERESTARTSYS;
233         }
234
235         mutex_lock(&device.item_list_lock);
236         PDEBUG(1, "got lock, pid: %d, secure_id: 0x%x, ref_count: %d\n", lock_cmd->pid, lock_item->secure_id, device.items[i_index].references[ref_index].ref_count);
237         device.items[i_index].owner = lock_cmd->pid;
238         mutex_unlock(&device.item_list_lock);
239
240         return 0;
241 }
242
243 static int do_umplock_release(_lock_cmd_priv *lock_cmd)
244 {
245         int ret, i_index, ref_index, call_up;
246         _lock_item_s *lock_item = (_lock_item_s *)&lock_cmd->msg;
247
248         mutex_lock(&device.item_list_lock);
249
250         if (0 == lock_item->secure_id) {
251                 PERROR("IOCTL_UMPLOCK_RELEASE called with secure_id is 0, pid: %d\n", lock_cmd->pid);
252                 mutex_unlock(&device.item_list_lock);
253                 return -EINVAL;
254         }
255
256         ret = umplock_find_client_valid(lock_cmd->pid);
257         if (ret < 0) {
258                 /*lock request from an invalid client pid, do nothing*/
259                 mutex_unlock(&device.item_list_lock);
260                 return -EPERM;
261         }
262
263         i_index = ref_index = -1;
264
265         ret = umplock_find_item_by_pid(lock_cmd, &i_index, &ref_index);
266         if (ret < 0) {
267                 /*fail to find item*/
268                 PERROR("IOCTL_UMPLOCK_RELEASE called with invalid parameter pid: %d, secid: 0x%x\n", lock_cmd->pid, lock_item->secure_id);
269                 mutex_unlock(&device.item_list_lock);
270                 return -EINVAL;
271         }
272
273         /* if the lock is not owned by this process */
274         if (lock_cmd->pid != device.items[i_index].owner) {
275                 mutex_unlock(&device.item_list_lock);
276                 return -EPERM;
277         }
278
279         /* if the ref_count is 0, that means nothing to unlock, just return */
280         if (0 == device.items[i_index].references[ref_index].ref_count) {
281                 mutex_unlock(&device.item_list_lock);
282                 return 0;
283         }
284
285         device.items[i_index].references[ref_index].ref_count--;
286         device.items[i_index].id_ref_count--;
287         PDEBUG(1, "unlock, pid: %d, secure_id: 0x%x, ref_count: %d\n", lock_cmd->pid, lock_item->secure_id, device.items[i_index].references[ref_index].ref_count);
288
289         call_up = 0;
290         if (device.items[i_index].references[ref_index].down_count > 1) {
291                 call_up = 1;
292                 device.items[i_index].references[ref_index].down_count--;
293         }
294         if (0 == device.items[i_index].references[ref_index].ref_count) {
295                 device.items[i_index].references[ref_index].pid = 0;
296                 if (0 == device.items[i_index].id_ref_count) {
297                         PDEBUG(1, "release item, pid: %d, secure_id: 0x%x\n", lock_cmd->pid, lock_item->secure_id);
298                         device.items[i_index].secure_id = 0;
299                 }
300                 device.items[i_index].owner = 0;
301                 call_up = 1;
302         }
303         if (call_up) {
304                 PDEBUG(1, "call up, pid: %d, secure_id: 0x%x\n", lock_cmd->pid, lock_item->secure_id);
305                 up(&device.items[i_index].item_lock);
306         }
307         mutex_unlock(&device.item_list_lock);
308
309         return 0;
310 }
311
312 static int do_umplock_zap(void)
313 {
314         int i;
315
316         PDEBUG(1, "ZAP ALL ENTRIES!\n");
317
318         mutex_lock(&device.item_list_lock);
319
320         for (i = 0; i < MAX_ITEMS; i++) {
321                 device.items[i].secure_id = 0;
322                 memset(&device.items[i].references, 0, sizeof(_lock_ref) * MAX_PIDS);
323                 sema_init(&device.items[i].item_lock, 1);
324         }
325
326         for (i = 0; i < MAX_PIDS; i++) {
327                 device.pids[i] = 0;
328         }
329         mutex_unlock(&device.item_list_lock);
330
331         return 0;
332 }
333
334 static int do_umplock_dump(void)
335 {
336         int i, j;
337
338         mutex_lock(&device.item_list_lock);
339         PERROR("dump all the items begin\n");
340         for (i = 0; i < MAX_ITEMS; i++) {
341                 for (j = 0; j < MAX_PIDS; j++) {
342                         if (device.items[i].secure_id != 0 && device.items[i].references[j].pid != 0) {
343                                 PERROR("item[%d]->secure_id=0x%x, owner=%d\t reference[%d].ref_count=%d.pid=%d\n",
344                                        i,
345                                        device.items[i].secure_id,
346                                        device.items[i].owner,
347                                        j,
348                                        device.items[i].references[j].ref_count,
349                                        device.items[i].references[j].pid);
350                         }
351                 }
352         }
353         PERROR("dump all the items end\n");
354         mutex_unlock(&device.item_list_lock);
355
356         return 0;
357 }
358
359 int do_umplock_client_add(_lock_cmd_priv *lock_cmd)
360 {
361         int i;
362         mutex_lock(&device.item_list_lock);
363         for (i = 0; i < MAX_PIDS; i++) {
364                 if (device.pids[i] == lock_cmd->pid) {
365                         mutex_unlock(&device.item_list_lock);
366                         return 0;
367                 }
368         }
369         for (i = 0; i < MAX_PIDS; i++) {
370                 if (device.pids[i] == 0) {
371                         device.pids[i] = lock_cmd->pid;
372                         break;
373                 }
374         }
375         mutex_unlock(&device.item_list_lock);
376         if (i == MAX_PIDS) {
377                 PERROR("Oops, Run out of client slots\n ");
378                 return -EINVAL;
379         }
380         return 0;
381 }
382
383 int do_umplock_client_delete(_lock_cmd_priv *lock_cmd)
384 {
385         int p_index = -1, i_index = -1, ref_index = -1;
386         int ret;
387         _lock_item_s *lock_item;
388         lock_item = (_lock_item_s *)&lock_cmd->msg;
389
390         mutex_lock(&device.item_list_lock);
391         p_index = umplock_find_client_valid(lock_cmd->pid);
392         /*lock item pid is not valid.*/
393         if (p_index < 0) {
394                 mutex_unlock(&device.item_list_lock);
395                 return 0;
396         }
397
398         /*walk through umplock item list and release reference attached to this client*/
399         for (i_index = 0; i_index < MAX_ITEMS; i_index++) {
400                 lock_item->secure_id = device.items[i_index].secure_id;
401
402                 /*find the item index and reference slot for the lock_item*/
403                 ret = umplock_find_item_by_pid(lock_cmd, &i_index, &ref_index);
404
405                 if (ret < 0) {
406                         /*client has no reference on this umplock item, skip*/
407                         continue;
408                 }
409                 while (device.items[i_index].references[ref_index].ref_count) {
410                         /*release references on this client*/
411
412                         PDEBUG(1, "delete client, pid: %d, ref_count: %d\n", lock_cmd->pid, device.items[i_index].references[ref_index].ref_count);
413
414                         mutex_unlock(&device.item_list_lock);
415                         do_umplock_release(lock_cmd);
416                         mutex_lock(&device.item_list_lock);
417                 }
418         }
419
420         /*remove the pid from umplock valid pid list*/
421         device.pids[p_index] = 0;
422         mutex_unlock(&device.item_list_lock);
423
424         return 0;
425 }
426
427 static long umplock_driver_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
428 {
429         int ret;
430         uint32_t size = _IOC_SIZE(cmd);
431         _lock_cmd_priv lock_cmd ;
432
433         if (_IOC_TYPE(cmd) != LOCK_IOCTL_GROUP) {
434                 return -ENOTTY;
435         }
436
437         if (_IOC_NR(cmd) >= LOCK_IOCTL_MAX_CMDS) {
438                 return -ENOTTY;
439         }
440
441         switch (cmd) {
442         case LOCK_IOCTL_CREATE:
443                 if (size != sizeof(_lock_item_s)) {
444                         return -ENOTTY;
445                 }
446
447                 if (copy_from_user(&lock_cmd.msg, (void __user *)arg, size)) {
448                         return -EFAULT;
449                 }
450                 lock_cmd.pid = (u32)current->tgid;
451                 ret = do_umplock_create(&lock_cmd);
452                 if (ret) {
453                         return ret;
454                 }
455                 return 0;
456
457         case LOCK_IOCTL_PROCESS:
458                 if (size != sizeof(_lock_item_s)) {
459                         return -ENOTTY;
460                 }
461
462                 if (copy_from_user(&lock_cmd.msg, (void __user *)arg, size)) {
463                         return -EFAULT;
464                 }
465                 lock_cmd.pid = (u32)current->tgid;
466                 return do_umplock_process(&lock_cmd);
467
468         case LOCK_IOCTL_RELEASE:
469                 if (size != sizeof(_lock_item_s)) {
470                         return -ENOTTY;
471                 }
472
473                 if (copy_from_user(&lock_cmd.msg, (void __user *)arg, size)) {
474                         return -EFAULT;
475                 }
476                 lock_cmd.pid = (u32)current->tgid;
477                 ret = do_umplock_release(&lock_cmd);
478                 if (ret) {
479                         return ret;
480                 }
481                 return 0;
482
483         case LOCK_IOCTL_ZAP:
484                 do_umplock_zap();
485                 return 0;
486
487         case LOCK_IOCTL_DUMP:
488                 do_umplock_dump();
489                 return 0;
490         }
491
492         return -ENOIOCTLCMD;
493 }
494
495 static int umplock_driver_open(struct inode *inode, struct file *filp)
496 {
497         _lock_cmd_priv lock_cmd;
498
499         atomic_inc(&device.sessions);
500         PDEBUG(1, "OPEN SESSION (%i references)\n", atomic_read(&device.sessions));
501
502         lock_cmd.pid = (u32)current->tgid;
503         do_umplock_client_add(&lock_cmd);
504
505         return 0;
506 }
507
508 static int umplock_driver_release(struct inode *inode, struct file *filp)
509 {
510         int sessions = 0;
511         _lock_cmd_priv lock_cmd;
512
513         lock_cmd.pid = (u32)current->tgid;
514         do_umplock_client_delete(&lock_cmd);
515
516         mutex_lock(&device.item_list_lock);
517         atomic_dec(&device.sessions);
518         sessions = atomic_read(&device.sessions);
519         PDEBUG(1, "CLOSE SESSION (%i references)\n", sessions);
520         mutex_unlock(&device.item_list_lock);
521         if (sessions == 0) {
522                 do_umplock_zap();
523         }
524
525         return 0;
526 }
527
528 static struct file_operations umplock_fops = {
529         .owner   = THIS_MODULE,
530         .open    = umplock_driver_open,
531         .release = umplock_driver_release,
532         .unlocked_ioctl = umplock_driver_ioctl,
533 };
534
535 int umplock_device_initialize(void)
536 {
537         int err;
538
539         err = alloc_chrdev_region(&umplock_dev, 0, 1, umplock_dev_name);
540
541         if (0 == err) {
542                 memset(&umplock_device, 0, sizeof(umplock_device));
543                 cdev_init(&umplock_device.cdev, &umplock_fops);
544                 umplock_device.cdev.owner = THIS_MODULE;
545                 umplock_device.cdev.ops = &umplock_fops;
546
547                 err = cdev_add(&umplock_device.cdev, umplock_dev, 1);
548                 if (0 == err) {
549                         umplock_device.umplock_class = class_create(THIS_MODULE, umplock_dev_name);
550                         if (IS_ERR(umplock_device.umplock_class)) {
551                                 err = PTR_ERR(umplock_device.umplock_class);
552                         } else {
553                                 struct device *mdev;
554                                 mdev = device_create(umplock_device.umplock_class, NULL, umplock_dev, NULL, umplock_dev_name);
555                                 if (!IS_ERR(mdev)) {
556                                         return 0; /* all ok */
557                                 }
558
559                                 err = PTR_ERR(mdev);
560                                 class_destroy(umplock_device.umplock_class);
561                         }
562                         cdev_del(&umplock_device.cdev);
563                 }
564
565                 unregister_chrdev_region(umplock_dev, 1);
566         } else {
567                 PERROR("alloc chardev region failed\n");
568         }
569
570         return err;
571 }
572
573 void umplock_device_terminate(void)
574 {
575         device_destroy(umplock_device.umplock_class, umplock_dev);
576         class_destroy(umplock_device.umplock_class);
577
578         cdev_del(&umplock_device.cdev);
579         unregister_chrdev_region(umplock_dev, 1);
580 }
581
582 static int __init umplock_initialize_module(void)
583 {
584         PDEBUG(1, "Inserting UMP lock device driver. Compiled: %s, time: %s\n", __DATE__, __TIME__);
585
586         mutex_init(&device.item_list_lock);
587         if (umplock_device_initialize() != 0) {
588                 PERROR("UMP lock device driver init failed\n");
589                 return -ENOTTY;
590         }
591         memset(&device.items, 0, sizeof(umplock_item) * MAX_ITEMS);
592         memset(&device.pids, 0, sizeof(u32) * MAX_PIDS);
593         atomic_set(&device.sessions, 0);
594
595         PDEBUG(1, "UMP lock device driver loaded\n");
596
597         return 0;
598 }
599
600 static void __exit umplock_cleanup_module(void)
601 {
602         PDEBUG(1, "unloading UMP lock module\n");
603
604         memset(&device.items, 0, sizeof(umplock_item) * MAX_ITEMS);
605         memset(&device.pids, 0, sizeof(u32) * MAX_PIDS);
606         umplock_device_terminate();
607         mutex_destroy(&device.item_list_lock);
608
609         PDEBUG(1, "UMP lock module unloaded\n");
610 }
611
612 module_init(umplock_initialize_module);
613 module_exit(umplock_cleanup_module);
614
615
616 MODULE_LICENSE("GPL");
617 MODULE_AUTHOR("ARM Ltd.");
618 MODULE_DESCRIPTION("ARM UMP locker");