[FOSS_TLK]security: tlk_driver: new ss protocol support
[tegra/ote_partner/tlk_driver.git] / security / tlk_driver / ote_device.c
1 /*
2  * Copyright (c) 2013-2014 NVIDIA Corporation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18
19 #include <linux/atomic.h>
20 #include <linux/uaccess.h>
21 #include <linux/module.h>
22 #include <linux/slab.h>
23 #include <linux/fs.h>
24 #include <linux/printk.h>
25 #include <linux/ioctl.h>
26 #include <linux/miscdevice.h>
27 #include <linux/mm.h>
28 #include <asm/cacheflush.h>
29 #include <asm/outercache.h>
30 #include <linux/list.h>
31 #include <linux/dma-mapping.h>
32
33 #include "ote_protocol.h"
34
35 #define SET_ANSWER(a, r, ro)    { a.result = r; a.result_origin = ro; }
36
37 struct tlk_device tlk_dev;
38 DEFINE_MUTEX(smc_lock);
39
40 static int te_create_free_cmd_list(struct tlk_device *dev)
41 {
42         int cmd_desc_count, ret = 0;
43         struct te_cmd_req_desc *req_desc;
44         struct te_cmd_req_desc_compat *req_desc_compat;
45         int bitmap_size;
46         bool use_reqbuf;
47
48         /*
49          * Check if new shared req/param register SMC is supported.
50          *
51          * If it is, TLK can map in the shared req/param buffers and do_smc
52          * only needs to send the offsets within each (with cache coherency
53          * being maintained by HW through an NS mapping).
54          *
55          * If the SMC support is not yet present, then fallback to the old
56          * mode of writing to an uncached buffer to maintain coherency (and
57          * phys addresses are passed in do_smc).
58          */
59         dev->req_param_buf = NULL;
60         use_reqbuf = !tlk_generic_smc(TE_SMC_REGISTER_REQ_BUF, 0, 0);
61
62         if (use_reqbuf) {
63                 dev->req_param_buf = kmalloc((2 * PAGE_SIZE), GFP_KERNEL);
64
65                 /* requests in the first page, params in the second */
66                 dev->req_addr   = (struct te_request *) dev->req_param_buf;
67                 dev->param_addr = (struct te_oper_param *)
68                                         (dev->req_param_buf + PAGE_SIZE);
69
70                 tlk_generic_smc(TE_SMC_REGISTER_REQ_BUF,
71                                 (uintptr_t)dev->req_addr, (2 * PAGE_SIZE));
72         } else {
73                 dev->req_addr = dma_alloc_coherent(NULL, PAGE_SIZE,
74                                         &dev->req_addr_phys, GFP_KERNEL);
75                 dev->param_addr = dma_alloc_coherent(NULL, PAGE_SIZE,
76                                         &dev->param_addr_phys, GFP_KERNEL);
77         }
78
79         if (!dev->req_addr || !dev->param_addr || !dev->req_param_buf) {
80                 ret = -ENOMEM;
81                 goto error;
82         }
83
84         /* requests in the first page, params in the second */
85         dev->req_addr_compat   = (struct te_request_compat *)
86                                         dev->req_param_buf;
87         dev->param_addr_compat = (struct te_oper_param_compat *)
88                                         (dev->req_param_buf + PAGE_SIZE);
89
90         /* alloc param bitmap allocator */
91         bitmap_size = BITS_TO_LONGS(TE_PARAM_MAX) * sizeof(long);
92         dev->param_bitmap = kzalloc(bitmap_size, GFP_KERNEL);
93
94         for (cmd_desc_count = 0;
95                 cmd_desc_count < TE_CMD_DESC_MAX; cmd_desc_count++) {
96
97                 req_desc = kzalloc(sizeof(struct te_cmd_req_desc), GFP_KERNEL);
98                 if (req_desc == NULL) {
99                         pr_err("Failed to allocate cmd req descriptor\n");
100                         ret = -ENOMEM;
101                         goto error;
102                 }
103                 req_desc->req_addr = dev->req_addr + cmd_desc_count;
104                 INIT_LIST_HEAD(&(req_desc->list));
105
106                 /* Add the cmd param descriptor to free list */
107                 list_add_tail(&req_desc->list, &(dev->free_cmd_list));
108         }
109
110         for (cmd_desc_count = 0;
111                 cmd_desc_count < TE_CMD_DESC_MAX_COMPAT; cmd_desc_count++) {
112
113                 req_desc_compat = kzalloc(sizeof(struct te_cmd_req_desc_compat),
114                                 GFP_KERNEL);
115                 if (req_desc_compat == NULL) {
116                         pr_err("Failed to allocate cmd req descriptor\n");
117                         ret = -ENOMEM;
118                         goto error;
119                 }
120                 req_desc_compat->req_addr =
121                         dev->req_addr_compat + cmd_desc_count;
122                 INIT_LIST_HEAD(&(req_desc_compat->list));
123
124                 /* Add the cmd param descriptor to free list */
125                 list_add_tail(&req_desc_compat->list, &(dev->free_cmd_list));
126         }
127
128 error:
129         return ret;
130 }
131
132 static struct te_oper_param *te_get_free_params(struct tlk_device *dev,
133         unsigned int nparams)
134 {
135         struct te_oper_param *params = NULL;
136         int idx, nbits;
137
138         if (nparams) {
139                 nbits = get_count_order(nparams);
140                 idx = bitmap_find_free_region(dev->param_bitmap,
141                                 TE_PARAM_MAX, nbits);
142                 if (idx >= 0)
143                         params = dev->param_addr + idx;
144         }
145         return params;
146 }
147
148 static void te_put_free_params(struct tlk_device *dev,
149         struct te_oper_param *params, uint32_t nparams)
150 {
151         int idx, nbits;
152
153         idx = (params - dev->param_addr);
154         nbits = get_count_order(nparams);
155         bitmap_release_region(dev->param_bitmap, idx, nbits);
156 }
157
158 static struct te_oper_param_compat *
159         te_get_free_params_compat(struct tlk_device *dev, unsigned int nparams)
160 {
161         struct te_oper_param_compat *params = NULL;
162         int idx, nbits;
163
164         if (nparams) {
165                 nbits = get_count_order(nparams);
166                 idx = bitmap_find_free_region(dev->param_bitmap,
167                                 TE_PARAM_MAX, nbits);
168                 if (idx >= 0)
169                         params = dev->param_addr_compat + idx;
170         }
171         return params;
172 }
173
174 static void te_put_free_params_compat(struct tlk_device *dev,
175         struct te_oper_param_compat *params, uint32_t nparams)
176 {
177         int idx, nbits;
178
179         idx = (params - dev->param_addr_compat);
180         nbits = get_count_order(nparams);
181         bitmap_release_region(dev->param_bitmap, idx, nbits);
182 }
183
184 static struct te_cmd_req_desc *te_get_free_cmd_desc(struct tlk_device *dev)
185 {
186         struct te_cmd_req_desc *cmd_desc = NULL;
187
188         if (!(list_empty(&(dev->free_cmd_list)))) {
189                 cmd_desc = list_first_entry(&(dev->free_cmd_list),
190                                 struct te_cmd_req_desc, list);
191                 list_del(&(cmd_desc->list));
192                 list_add_tail(&cmd_desc->list, &(dev->used_cmd_list));
193         }
194         return cmd_desc;
195 }
196
197 static void te_put_used_cmd_desc(struct tlk_device *dev,
198         struct te_cmd_req_desc *cmd_desc)
199 {
200         struct te_cmd_req_desc *param_desc, *tmp_param_desc;
201
202         if (cmd_desc) {
203                 list_for_each_entry_safe(param_desc, tmp_param_desc,
204                                 &(dev->used_cmd_list), list) {
205                         if (cmd_desc->req_addr == param_desc->req_addr) {
206                                 list_del(&param_desc->list);
207                                 list_add_tail(&param_desc->list,
208                                         &(dev->free_cmd_list));
209                         }
210                 }
211         }
212 }
213
214 static struct te_cmd_req_desc_compat *
215 te_get_free_cmd_desc_compat(struct tlk_device *dev)
216 {
217         struct te_cmd_req_desc_compat *cmd_desc = NULL;
218
219         if (!(list_empty(&(dev->free_cmd_list)))) {
220                 cmd_desc = list_first_entry(&(dev->free_cmd_list),
221                                 struct te_cmd_req_desc_compat, list);
222                 list_del(&(cmd_desc->list));
223                 list_add_tail(&cmd_desc->list, &(dev->used_cmd_list));
224         }
225         return cmd_desc;
226 }
227
228 static void te_put_used_cmd_desc_compat(struct tlk_device *dev,
229         struct te_cmd_req_desc_compat *cmd_desc)
230 {
231         struct te_cmd_req_desc_compat *param_desc, *tmp_param_desc;
232
233         if (cmd_desc) {
234                 list_for_each_entry_safe(param_desc, tmp_param_desc,
235                                 &(dev->used_cmd_list), list) {
236                         if (cmd_desc->req_addr == param_desc->req_addr) {
237                                 list_del(&param_desc->list);
238                                 list_add_tail(&param_desc->list,
239                                         &(dev->free_cmd_list));
240                         }
241                 }
242         }
243 }
244
245 static void __attribute__((unused)) te_print_cmd_list(
246         struct tlk_device *dev, int used_list)
247 {
248         struct te_cmd_req_desc *param_desc;
249
250         if (!used_list) {
251                 pr_info("Printing free cmd list\n");
252                 if (!(list_empty(&(dev->free_cmd_list)))) {
253                         list_for_each_entry(param_desc, &(dev->free_cmd_list),
254                                         list)
255                                 pr_info("Phys addr for cmd req desc (%p)\n",
256                                         param_desc->req_addr);
257                 }
258         } else {
259                 pr_info("Printing used cmd list\n");
260                 if (!(list_empty(&(dev->used_cmd_list)))) {
261                         list_for_each_entry(param_desc, &(dev->used_cmd_list),
262                                         list)
263                                 pr_info("Phys addr for cmd req desc (%p)\n",
264                                         param_desc->req_addr);
265                 }
266         }
267 }
268
269 static int tlk_device_open(struct inode *inode, struct file *file)
270 {
271         struct tlk_context *context;
272         int ret = 0;
273
274         context = kzalloc(sizeof(struct tlk_context), GFP_KERNEL);
275         if (!context) {
276                 ret = -ENOMEM;
277                 goto error;
278         }
279         context->dev = &tlk_dev;
280         INIT_LIST_HEAD(&(context->temp_shmem_list));
281         INIT_LIST_HEAD(&(context->persist_shmem_list));
282
283         file->private_data = context;
284         return 0;
285 error:
286         return ret;
287 }
288
289 static int tlk_device_release(struct inode *inode, struct file *file)
290 {
291         kfree(file->private_data);
292         file->private_data = NULL;
293         return 0;
294 }
295
296 static int copy_params_from_user(struct te_request *req,
297         struct te_operation *operation)
298 {
299         struct te_oper_param *param_array;
300         struct te_oper_param *user_param;
301         uint32_t i;
302
303         if (operation->list_count == 0)
304                 return 0;
305
306         param_array = req->params;
307         if (param_array == NULL) {
308                 pr_err("param_array empty\n");
309                 return 1;
310         }
311
312         user_param = operation->list_head;
313         for (i = 0; i < operation->list_count && user_param != NULL; i++) {
314                 if (copy_from_user(param_array + i, user_param,
315                                         sizeof(struct te_oper_param))) {
316                         pr_err("Failed to copy operation parameter:%d, %p, " \
317                                         "list_count: %d\n",
318                                         i, user_param, operation->list_count);
319                         return 1;
320                 }
321                 user_param = param_array[i].next_ptr_user;
322         }
323         return 0;
324 }
325
326 static int copy_params_to_user(struct te_request *req,
327         struct te_operation *operation)
328 {
329         struct te_oper_param *param_array;
330         struct te_oper_param *user_param;
331         uint32_t i;
332
333         if (operation->list_count == 0)
334                 return 0;
335
336         param_array = req->params;
337         if (param_array == NULL) {
338                 pr_err("param_array empty\n");
339                 return 1;
340         }
341
342         user_param = operation->list_head;
343         for (i = 0; i < req->params_size; i++) {
344                 if (copy_to_user(user_param, param_array + i,
345                                         sizeof(struct te_oper_param))) {
346                         pr_err("Failed to copy back parameter:%d %p\n", i,
347                                         user_param);
348                         return 1;
349                 }
350                 user_param = param_array[i].next_ptr_user;
351         }
352         return 0;
353 }
354
355 static long te_handle_trustedapp_ioctl(struct file *file,
356         unsigned int ioctl_num, unsigned long ioctl_param)
357 {
358         long err = 0;
359         union te_cmd cmd;
360         void *ptr_user_answer = NULL;
361         struct te_operation *operation = NULL;
362         struct te_oper_param *params = NULL;
363         struct te_answer answer;
364         struct te_request *request;
365
366         struct te_cmd_req_desc *cmd_desc = NULL;
367         struct tlk_context *context = file->private_data;
368         struct tlk_device *dev = context->dev;
369
370         if (copy_from_user(&cmd, (void __user *)ioctl_param,
371                                 sizeof(union te_cmd))) {
372                 pr_err("Failed to copy command request\n");
373                 err = -EFAULT;
374                 goto error;
375         }
376
377         memset(&answer, 0, sizeof(struct te_answer));
378
379         switch (ioctl_num) {
380         case TE_IOCTL_OPEN_CLIENT_SESSION:
381                 operation = &cmd.opensession.operation;
382                 ptr_user_answer = (void *)cmd.opensession.answer;
383
384                 cmd_desc = te_get_free_cmd_desc(dev);
385                 params = te_get_free_params(dev, operation->list_count);
386
387                 if (!cmd_desc || (operation->list_count && !params)) {
388                         SET_ANSWER(answer,
389                                    OTE_ERROR_OUT_OF_MEMORY,
390                                    OTE_RESULT_ORIGIN_COMMS);
391                         pr_err("failed to get cmd_desc/params\n");
392                         goto error;
393                 }
394
395                 request = cmd_desc->req_addr;
396                 memset(request, 0, sizeof(struct te_request));
397
398                 request->params = params;
399                 request->params_size = operation->list_count;
400
401                 if (copy_params_from_user(request, operation)) {
402                         err = -EFAULT;
403                         pr_info("failed to copy params from user\n");
404                         goto error;
405                 }
406
407                 te_open_session(&cmd.opensession, request, context);
408
409                 SET_ANSWER(answer, request->result, request->result_origin);
410                 answer.session_id = request->session_id;
411                 break;
412
413         case TE_IOCTL_CLOSE_CLIENT_SESSION:
414                 ptr_user_answer = (void *)cmd.closesession.answer;
415                 cmd_desc = te_get_free_cmd_desc(dev);
416                 if (!cmd_desc) {
417                         SET_ANSWER(answer,
418                                    OTE_ERROR_OUT_OF_MEMORY,
419                                    OTE_RESULT_ORIGIN_COMMS);
420                         pr_err("failed to get cmd_desc\n");
421                         goto error;
422                 }
423
424                 request = cmd_desc->req_addr;
425                 memset(request, 0, sizeof(struct te_request));
426
427                 /* close session cannot fail */
428                 te_close_session(&cmd.closesession, request, context);
429                 break;
430
431         case TE_IOCTL_LAUNCH_OPERATION:
432                 operation = &cmd.launchop.operation;
433                 ptr_user_answer = (void *)cmd.launchop.answer;
434
435                 cmd_desc = te_get_free_cmd_desc(dev);
436                 params = te_get_free_params(dev, operation->list_count);
437
438                 if (!cmd_desc || (operation->list_count && !params)) {
439                         SET_ANSWER(answer,
440                                    OTE_ERROR_OUT_OF_MEMORY,
441                                    OTE_RESULT_ORIGIN_COMMS);
442                         pr_err("failed to get cmd_desc/params\n");
443                         goto error;
444                 }
445
446                 request = cmd_desc->req_addr;
447                 memset(request, 0, sizeof(struct te_request));
448
449                 request->params = params;
450                 request->params_size = operation->list_count;
451
452                 if (copy_params_from_user(request, operation)) {
453                         err = -EFAULT;
454                         pr_info("failed to copy params from user\n");
455                         goto error;
456                 }
457
458                 te_launch_operation(&cmd.launchop, request, context);
459
460                 SET_ANSWER(answer, request->result, request->result_origin);
461                 break;
462
463         default:
464                 pr_err("Invalid IOCTL Cmd\n");
465                 err = -EINVAL;
466                 goto error;
467         }
468         if (ptr_user_answer && !err) {
469                 if (copy_to_user(ptr_user_answer, &answer,
470                         sizeof(struct te_answer))) {
471                         pr_err("Failed to copy answer\n");
472                         err = -EFAULT;
473                 }
474         }
475         if (request->params && !err) {
476                 if (copy_params_to_user(request, operation)) {
477                         pr_err("Failed to copy return params\n");
478                         err = -EFAULT;
479                 }
480         }
481
482 error:
483         if (cmd_desc)
484                 te_put_used_cmd_desc(dev, cmd_desc);
485         if (params)
486                 te_put_free_params(dev, params, operation->list_count);
487         return err;
488 }
489
490 static int copy_params_from_user_compat(struct te_request_compat *req,
491         struct te_operation_compat *operation)
492 {
493         struct te_oper_param_compat *param_array;
494         struct te_oper_param_compat *user_param;
495         uint32_t i;
496
497         if (operation->list_count == 0)
498                 return 0;
499
500         param_array = (struct te_oper_param_compat *)(uintptr_t)req->params;
501         if (param_array == NULL) {
502                 pr_err("param_array empty\n");
503                 return 1;
504         }
505
506         user_param = (struct te_oper_param_compat *)(uintptr_t)
507                 operation->list_head;
508         for (i = 0; i < operation->list_count && user_param != NULL; i++) {
509                 if (copy_from_user(param_array + i, user_param,
510                                         sizeof(struct te_oper_param_compat))) {
511                         pr_err("Failed to copy operation parameter:%d, %p, " \
512                                         "list_count: %d\n",
513                                         i, user_param, operation->list_count);
514                         return 1;
515                 }
516                 user_param = (struct te_oper_param_compat *)(uintptr_t)
517                         param_array[i].next_ptr_user;
518         }
519         return 0;
520 }
521
522 static int copy_params_to_user_compat(struct te_request_compat *req,
523         struct te_operation_compat *operation)
524 {
525         struct te_oper_param_compat *param_array;
526         struct te_oper_param_compat *user_param;
527         uint32_t i;
528
529         if (operation->list_count == 0)
530                 return 0;
531
532         param_array =
533                 (struct te_oper_param_compat *)(uintptr_t)req->params;
534         if (param_array == NULL) {
535                 pr_err("param_array empty\n");
536                 return 1;
537         }
538
539         user_param =
540                 (struct te_oper_param_compat *)(uintptr_t)operation->list_head;
541         for (i = 0; i < req->params_size; i++) {
542                 if (copy_to_user(user_param, param_array + i,
543                                         sizeof(struct te_oper_param_compat))) {
544                         pr_err("Failed to copy back parameter:%d %p\n", i,
545                                         user_param);
546                         return 1;
547                 }
548                 user_param = (struct te_oper_param_compat *)(uintptr_t)
549                         param_array[i].next_ptr_user;
550         }
551         return 0;
552 }
553
554 static long te_handle_trustedapp_ioctl_compat(struct file *file,
555         unsigned int ioctl_num, unsigned long ioctl_param)
556 {
557         long err = 0;
558         union te_cmd_compat cmd_compat;
559         struct te_operation_compat *operation = NULL;
560         struct te_oper_param_compat *params = NULL;
561         struct te_request_compat *request;
562         void __user *ptr_user_answer = NULL;
563         struct te_answer answer;
564         struct te_cmd_req_desc_compat *cmd_desc = NULL;
565         struct tlk_context *context = file->private_data;
566         struct tlk_device *dev = context->dev;
567
568         if (copy_from_user(&cmd_compat, (void __user *)ioctl_param,
569                                 sizeof(union te_cmd_compat))) {
570                 pr_err("Failed to copy command request\n");
571                 err = -EFAULT;
572                 goto error;
573         }
574
575         memset(&answer, 0, sizeof(struct te_answer));
576
577         switch (ioctl_num) {
578         case TE_IOCTL_OPEN_CLIENT_SESSION_COMPAT:
579                 operation = &cmd_compat.opensession.operation;
580                 ptr_user_answer = (void *)(uintptr_t)
581                                         cmd_compat.opensession.answer;
582
583                 cmd_desc = te_get_free_cmd_desc_compat(dev);
584                 params = te_get_free_params_compat(dev, operation->list_count);
585
586                 if (!cmd_desc || (operation->list_count && !params)) {
587                         SET_ANSWER(answer,
588                                    OTE_ERROR_OUT_OF_MEMORY,
589                                    OTE_RESULT_ORIGIN_COMMS);
590                         pr_err("failed to get cmd_desc/params\n");
591                         goto error;
592                 }
593
594                 request = cmd_desc->req_addr;
595                 memset(request, 0, sizeof(struct te_request_compat));
596
597                 request->params = (uintptr_t)params;
598                 request->params_size = operation->list_count;
599
600                 if (copy_params_from_user_compat(request, operation)) {
601                         err = -EFAULT;
602                         pr_info("failed to copy params from user\n");
603                         goto error;
604                 }
605
606                 te_open_session_compat(&cmd_compat.opensession,
607                                         request, context);
608
609                 SET_ANSWER(answer, request->result, request->result_origin);
610                 answer.session_id = request->session_id;
611                 break;
612
613         case TE_IOCTL_CLOSE_CLIENT_SESSION_COMPAT:
614                 ptr_user_answer = (void *)(uintptr_t)
615                                         cmd_compat.closesession.answer;
616                 cmd_desc = te_get_free_cmd_desc_compat(dev);
617                 if (!cmd_desc) {
618                         SET_ANSWER(answer,
619                                    OTE_ERROR_OUT_OF_MEMORY,
620                                    OTE_RESULT_ORIGIN_COMMS);
621                         pr_err("failed to get cmd_desc\n");
622                         goto error;
623                 }
624
625                 request = cmd_desc->req_addr;
626                 memset(request, 0, sizeof(struct te_request_compat));
627
628                 /* close session cannot fail */
629                 te_close_session_compat(&cmd_compat.closesession,
630                                         request, context);
631                 break;
632
633         case TE_IOCTL_LAUNCH_OPERATION_COMPAT:
634                 operation = &cmd_compat.launchop.operation;
635                 ptr_user_answer = (void *)(uintptr_t)cmd_compat.launchop.answer;
636
637                 cmd_desc = te_get_free_cmd_desc_compat(dev);
638                 params = te_get_free_params_compat(dev, operation->list_count);
639
640                 if (!cmd_desc || (operation->list_count && !params)) {
641                         SET_ANSWER(answer,
642                                    OTE_ERROR_OUT_OF_MEMORY,
643                                    OTE_RESULT_ORIGIN_COMMS);
644                         pr_err("failed to get cmd_desc/params\n");
645                         goto error;
646                 }
647
648                 request = cmd_desc->req_addr;
649                 memset(request, 0, sizeof(struct te_request_compat));
650
651                 request->params = (uintptr_t)params;
652                 request->params_size = operation->list_count;
653
654                 if (copy_params_from_user_compat(request, operation)) {
655                         err = -EFAULT;
656                         pr_info("failed to copy params from user\n");
657                         goto error;
658                 }
659
660                 te_launch_operation_compat(&cmd_compat.launchop,
661                                                 request, context);
662
663                 SET_ANSWER(answer, request->result, request->result_origin);
664                 break;
665
666         default:
667                 pr_err("Invalid IOCTL Cmd\n");
668                 err = -EINVAL;
669                 goto error;
670         }
671         if (ptr_user_answer && !err) {
672                 if (copy_to_user(ptr_user_answer, &answer,
673                         sizeof(struct te_answer))) {
674                         pr_err("Failed to copy answer\n");
675                         err = -EFAULT;
676                 }
677         }
678         if (request->params && !err) {
679                 if (copy_params_to_user_compat(request, operation)) {
680                         pr_err("Failed to copy return params\n");
681                         err = -EFAULT;
682                 }
683         }
684
685 error:
686         if (cmd_desc)
687                 te_put_used_cmd_desc_compat(dev, cmd_desc);
688         if (params)
689                 te_put_free_params_compat(dev, params, operation->list_count);
690         return err;
691 }
692
693 static long tlk_device_ioctl(struct file *file, unsigned int ioctl_num,
694         unsigned long ioctl_param)
695 {
696         int err;
697
698         switch (ioctl_num) {
699         case TE_IOCTL_OPEN_CLIENT_SESSION:
700         case TE_IOCTL_CLOSE_CLIENT_SESSION:
701         case TE_IOCTL_LAUNCH_OPERATION:
702                 mutex_lock(&smc_lock);
703                 err = te_handle_trustedapp_ioctl(file, ioctl_num, ioctl_param);
704                 mutex_unlock(&smc_lock);
705                 break;
706
707         case TE_IOCTL_OPEN_CLIENT_SESSION_COMPAT:
708         case TE_IOCTL_CLOSE_CLIENT_SESSION_COMPAT:
709         case TE_IOCTL_LAUNCH_OPERATION_COMPAT:
710                 mutex_lock(&smc_lock);
711                 err = te_handle_trustedapp_ioctl_compat(file, ioctl_num,
712                                                         ioctl_param);
713                 mutex_unlock(&smc_lock);
714                 break;
715
716         case TE_IOCTL_SS_NEW_REQ_LEGACY:
717         case TE_IOCTL_SS_REQ_COMPLETE_LEGACY:
718                 err = te_handle_ss_ioctl_legacy(file, ioctl_num, ioctl_param);
719                 break;
720
721         case TE_IOCTL_SS_NEW_REQ:
722         case TE_IOCTL_SS_REQ_COMPLETE:
723         case TE_IOCTL_SS_CMD:
724                 err = te_handle_ss_ioctl(file, ioctl_num, ioctl_param);
725                 break;
726
727         default:
728                 pr_err("%s: Invalid IOCTL (0x%x) id 0x%x max 0x%lx\n",
729                         __func__, ioctl_num, _IOC_NR(ioctl_num),
730                         (unsigned long)TE_IOCTL_MAX_NR);
731                 err = -EINVAL;
732                 break;
733         }
734
735         return err;
736 }
737
738 /*
739  * tlk_driver function definitions.
740  */
741 static const struct file_operations tlk_device_fops = {
742         .owner = THIS_MODULE,
743         .open = tlk_device_open,
744         .release = tlk_device_release,
745         .unlocked_ioctl = tlk_device_ioctl,
746 #ifdef CONFIG_COMPAT
747         .compat_ioctl = tlk_device_ioctl,
748 #endif
749 };
750
751 struct miscdevice tlk_misc_device = {
752         .minor = MISC_DYNAMIC_MINOR,
753         .name = "tlk_device",
754         .fops = &tlk_device_fops,
755 };
756
757 static int __init tlk_init(void)
758 {
759         int ret;
760
761         INIT_LIST_HEAD(&(tlk_dev.used_cmd_list));
762         INIT_LIST_HEAD(&(tlk_dev.free_cmd_list));
763
764         ret = te_create_free_cmd_list(&tlk_dev);
765         if (ret != 0)
766                 return ret;
767
768         return misc_register(&tlk_misc_device);
769 }
770
771 module_init(tlk_init);