32a2b65bf36e092ea29a0f70d7be4e244e56e9b5
[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->shmem_alloc_list));
281
282         file->private_data = context;
283         return 0;
284 error:
285         return ret;
286 }
287
288 static int tlk_device_release(struct inode *inode, struct file *file)
289 {
290         kfree(file->private_data);
291         file->private_data = NULL;
292         return 0;
293 }
294
295 static int copy_params_from_user(struct te_request *req,
296         struct te_operation *operation)
297 {
298         struct te_oper_param *param_array;
299         struct te_oper_param *user_param;
300         uint32_t i;
301
302         if (operation->list_count == 0)
303                 return 0;
304
305         param_array = req->params;
306         if (param_array == NULL) {
307                 pr_err("param_array empty\n");
308                 return 1;
309         }
310
311         user_param = operation->list_head;
312         for (i = 0; i < operation->list_count && user_param != NULL; i++) {
313                 if (copy_from_user(param_array + i, user_param,
314                                         sizeof(struct te_oper_param))) {
315                         pr_err("Failed to copy operation parameter:%d, %p, " \
316                                         "list_count: %d\n",
317                                         i, user_param, operation->list_count);
318                         return 1;
319                 }
320                 user_param = param_array[i].next_ptr_user;
321         }
322         return 0;
323 }
324
325 static int copy_params_to_user(struct te_request *req,
326         struct te_operation *operation)
327 {
328         struct te_oper_param *param_array;
329         struct te_oper_param *user_param;
330         uint32_t i;
331
332         if (operation->list_count == 0)
333                 return 0;
334
335         param_array = req->params;
336         if (param_array == NULL) {
337                 pr_err("param_array empty\n");
338                 return 1;
339         }
340
341         user_param = operation->list_head;
342         for (i = 0; i < req->params_size; i++) {
343                 if (copy_to_user(user_param, param_array + i,
344                                         sizeof(struct te_oper_param))) {
345                         pr_err("Failed to copy back parameter:%d %p\n", i,
346                                         user_param);
347                         return 1;
348                 }
349                 user_param = param_array[i].next_ptr_user;
350         }
351         return 0;
352 }
353
354 static long te_handle_trustedapp_ioctl(struct file *file,
355         unsigned int ioctl_num, unsigned long ioctl_param)
356 {
357         long err = 0;
358         union te_cmd cmd;
359         void *ptr_user_answer = NULL;
360         struct te_operation *operation = NULL;
361         struct te_oper_param *params = NULL;
362         struct te_answer answer;
363         struct te_request *request;
364
365         struct te_cmd_req_desc *cmd_desc = NULL;
366         struct tlk_context *context = file->private_data;
367         struct tlk_device *dev = context->dev;
368
369         if (copy_from_user(&cmd, (void __user *)ioctl_param,
370                                 sizeof(union te_cmd))) {
371                 pr_err("Failed to copy command request\n");
372                 err = -EFAULT;
373                 goto error;
374         }
375
376         memset(&answer, 0, sizeof(struct te_answer));
377
378         switch (ioctl_num) {
379         case TE_IOCTL_OPEN_CLIENT_SESSION:
380                 operation = &cmd.opensession.operation;
381                 ptr_user_answer = (void *)cmd.opensession.answer;
382
383                 cmd_desc = te_get_free_cmd_desc(dev);
384                 params = te_get_free_params(dev, operation->list_count);
385
386                 if (!cmd_desc || (operation->list_count && !params)) {
387                         SET_ANSWER(answer,
388                                    OTE_ERROR_OUT_OF_MEMORY,
389                                    OTE_RESULT_ORIGIN_COMMS);
390                         pr_err("failed to get cmd_desc/params\n");
391                         goto error;
392                 }
393
394                 request = cmd_desc->req_addr;
395                 memset(request, 0, sizeof(struct te_request));
396
397                 request->params = params;
398                 request->params_size = operation->list_count;
399
400                 if (copy_params_from_user(request, operation)) {
401                         err = -EFAULT;
402                         pr_info("failed to copy params from user\n");
403                         goto error;
404                 }
405
406                 te_open_session(&cmd.opensession, request, context);
407
408                 SET_ANSWER(answer, request->result, request->result_origin);
409                 answer.session_id = request->session_id;
410                 break;
411
412         case TE_IOCTL_CLOSE_CLIENT_SESSION:
413                 ptr_user_answer = (void *)cmd.closesession.answer;
414                 cmd_desc = te_get_free_cmd_desc(dev);
415                 if (!cmd_desc) {
416                         SET_ANSWER(answer,
417                                    OTE_ERROR_OUT_OF_MEMORY,
418                                    OTE_RESULT_ORIGIN_COMMS);
419                         pr_err("failed to get cmd_desc\n");
420                         goto error;
421                 }
422
423                 request = cmd_desc->req_addr;
424                 memset(request, 0, sizeof(struct te_request));
425
426                 /* close session cannot fail */
427                 te_close_session(&cmd.closesession, request, context);
428                 break;
429
430         case TE_IOCTL_LAUNCH_OPERATION:
431                 operation = &cmd.launchop.operation;
432                 ptr_user_answer = (void *)cmd.launchop.answer;
433
434                 cmd_desc = te_get_free_cmd_desc(dev);
435                 params = te_get_free_params(dev, operation->list_count);
436
437                 if (!cmd_desc || (operation->list_count && !params)) {
438                         SET_ANSWER(answer,
439                                    OTE_ERROR_OUT_OF_MEMORY,
440                                    OTE_RESULT_ORIGIN_COMMS);
441                         pr_err("failed to get cmd_desc/params\n");
442                         goto error;
443                 }
444
445                 request = cmd_desc->req_addr;
446                 memset(request, 0, sizeof(struct te_request));
447
448                 request->params = params;
449                 request->params_size = operation->list_count;
450
451                 if (copy_params_from_user(request, operation)) {
452                         err = -EFAULT;
453                         pr_info("failed to copy params from user\n");
454                         goto error;
455                 }
456
457                 te_launch_operation(&cmd.launchop, request, context);
458
459                 SET_ANSWER(answer, request->result, request->result_origin);
460                 break;
461
462         default:
463                 pr_err("Invalid IOCTL Cmd\n");
464                 err = -EINVAL;
465                 goto error;
466         }
467         if (ptr_user_answer && !err) {
468                 if (copy_to_user(ptr_user_answer, &answer,
469                         sizeof(struct te_answer))) {
470                         pr_err("Failed to copy answer\n");
471                         err = -EFAULT;
472                 }
473         }
474         if (request->params && !err) {
475                 if (copy_params_to_user(request, operation)) {
476                         pr_err("Failed to copy return params\n");
477                         err = -EFAULT;
478                 }
479         }
480
481 error:
482         if (cmd_desc)
483                 te_put_used_cmd_desc(dev, cmd_desc);
484         if (params)
485                 te_put_free_params(dev, params, operation->list_count);
486         return err;
487 }
488
489 static int copy_params_from_user_compat(struct te_request_compat *req,
490         struct te_operation_compat *operation)
491 {
492         struct te_oper_param_compat *param_array;
493         struct te_oper_param_compat *user_param;
494         uint32_t i;
495
496         if (operation->list_count == 0)
497                 return 0;
498
499         param_array = (struct te_oper_param_compat *)(uintptr_t)req->params;
500         if (param_array == NULL) {
501                 pr_err("param_array empty\n");
502                 return 1;
503         }
504
505         user_param = (struct te_oper_param_compat *)(uintptr_t)
506                 operation->list_head;
507         for (i = 0; i < operation->list_count && user_param != NULL; i++) {
508                 if (copy_from_user(param_array + i, user_param,
509                                         sizeof(struct te_oper_param_compat))) {
510                         pr_err("Failed to copy operation parameter:%d, %p, " \
511                                         "list_count: %d\n",
512                                         i, user_param, operation->list_count);
513                         return 1;
514                 }
515                 user_param = (struct te_oper_param_compat *)(uintptr_t)
516                         param_array[i].next_ptr_user;
517         }
518         return 0;
519 }
520
521 static int copy_params_to_user_compat(struct te_request_compat *req,
522         struct te_operation_compat *operation)
523 {
524         struct te_oper_param_compat *param_array;
525         struct te_oper_param_compat *user_param;
526         uint32_t i;
527
528         if (operation->list_count == 0)
529                 return 0;
530
531         param_array =
532                 (struct te_oper_param_compat *)(uintptr_t)req->params;
533         if (param_array == NULL) {
534                 pr_err("param_array empty\n");
535                 return 1;
536         }
537
538         user_param =
539                 (struct te_oper_param_compat *)(uintptr_t)operation->list_head;
540         for (i = 0; i < req->params_size; i++) {
541                 if (copy_to_user(user_param, param_array + i,
542                                         sizeof(struct te_oper_param_compat))) {
543                         pr_err("Failed to copy back parameter:%d %p\n", i,
544                                         user_param);
545                         return 1;
546                 }
547                 user_param = (struct te_oper_param_compat *)(uintptr_t)
548                         param_array[i].next_ptr_user;
549         }
550         return 0;
551 }
552
553 static long te_handle_trustedapp_ioctl_compat(struct file *file,
554         unsigned int ioctl_num, unsigned long ioctl_param)
555 {
556         long err = 0;
557         union te_cmd_compat cmd_compat;
558         struct te_operation_compat *operation = NULL;
559         struct te_oper_param_compat *params = NULL;
560         struct te_request_compat *request;
561         void __user *ptr_user_answer = NULL;
562         struct te_answer answer;
563         struct te_cmd_req_desc_compat *cmd_desc = NULL;
564         struct tlk_context *context = file->private_data;
565         struct tlk_device *dev = context->dev;
566
567         if (copy_from_user(&cmd_compat, (void __user *)ioctl_param,
568                                 sizeof(union te_cmd_compat))) {
569                 pr_err("Failed to copy command request\n");
570                 err = -EFAULT;
571                 goto error;
572         }
573
574         memset(&answer, 0, sizeof(struct te_answer));
575
576         switch (ioctl_num) {
577         case TE_IOCTL_OPEN_CLIENT_SESSION_COMPAT:
578                 operation = &cmd_compat.opensession.operation;
579                 ptr_user_answer = (void *)(uintptr_t)
580                                         cmd_compat.opensession.answer;
581
582                 cmd_desc = te_get_free_cmd_desc_compat(dev);
583                 params = te_get_free_params_compat(dev, operation->list_count);
584
585                 if (!cmd_desc || (operation->list_count && !params)) {
586                         SET_ANSWER(answer,
587                                    OTE_ERROR_OUT_OF_MEMORY,
588                                    OTE_RESULT_ORIGIN_COMMS);
589                         pr_err("failed to get cmd_desc/params\n");
590                         goto error;
591                 }
592
593                 request = cmd_desc->req_addr;
594                 memset(request, 0, sizeof(struct te_request_compat));
595
596                 request->params = (uintptr_t)params;
597                 request->params_size = operation->list_count;
598
599                 if (copy_params_from_user_compat(request, operation)) {
600                         err = -EFAULT;
601                         pr_info("failed to copy params from user\n");
602                         goto error;
603                 }
604
605                 te_open_session_compat(&cmd_compat.opensession,
606                                         request, context);
607
608                 SET_ANSWER(answer, request->result, request->result_origin);
609                 answer.session_id = request->session_id;
610                 break;
611
612         case TE_IOCTL_CLOSE_CLIENT_SESSION_COMPAT:
613                 ptr_user_answer = (void *)(uintptr_t)
614                                         cmd_compat.closesession.answer;
615                 cmd_desc = te_get_free_cmd_desc_compat(dev);
616                 if (!cmd_desc) {
617                         SET_ANSWER(answer,
618                                    OTE_ERROR_OUT_OF_MEMORY,
619                                    OTE_RESULT_ORIGIN_COMMS);
620                         pr_err("failed to get cmd_desc\n");
621                         goto error;
622                 }
623
624                 request = cmd_desc->req_addr;
625                 memset(request, 0, sizeof(struct te_request_compat));
626
627                 /* close session cannot fail */
628                 te_close_session_compat(&cmd_compat.closesession,
629                                         request, context);
630                 break;
631
632         case TE_IOCTL_LAUNCH_OPERATION_COMPAT:
633                 operation = &cmd_compat.launchop.operation;
634                 ptr_user_answer = (void *)(uintptr_t)cmd_compat.launchop.answer;
635
636                 cmd_desc = te_get_free_cmd_desc_compat(dev);
637                 params = te_get_free_params_compat(dev, operation->list_count);
638
639                 if (!cmd_desc || (operation->list_count && !params)) {
640                         SET_ANSWER(answer,
641                                    OTE_ERROR_OUT_OF_MEMORY,
642                                    OTE_RESULT_ORIGIN_COMMS);
643                         pr_err("failed to get cmd_desc/params\n");
644                         goto error;
645                 }
646
647                 request = cmd_desc->req_addr;
648                 memset(request, 0, sizeof(struct te_request_compat));
649
650                 request->params = (uintptr_t)params;
651                 request->params_size = operation->list_count;
652
653                 if (copy_params_from_user_compat(request, operation)) {
654                         err = -EFAULT;
655                         pr_info("failed to copy params from user\n");
656                         goto error;
657                 }
658
659                 te_launch_operation_compat(&cmd_compat.launchop,
660                                                 request, context);
661
662                 SET_ANSWER(answer, request->result, request->result_origin);
663                 break;
664
665         default:
666                 pr_err("Invalid IOCTL Cmd\n");
667                 err = -EINVAL;
668                 goto error;
669         }
670         if (ptr_user_answer && !err) {
671                 if (copy_to_user(ptr_user_answer, &answer,
672                         sizeof(struct te_answer))) {
673                         pr_err("Failed to copy answer\n");
674                         err = -EFAULT;
675                 }
676         }
677         if (request->params && !err) {
678                 if (copy_params_to_user_compat(request, operation)) {
679                         pr_err("Failed to copy return params\n");
680                         err = -EFAULT;
681                 }
682         }
683
684 error:
685         if (cmd_desc)
686                 te_put_used_cmd_desc_compat(dev, cmd_desc);
687         if (params)
688                 te_put_free_params_compat(dev, params, operation->list_count);
689         return err;
690 }
691
692 static long tlk_device_ioctl(struct file *file, unsigned int ioctl_num,
693         unsigned long ioctl_param)
694 {
695         int err;
696
697         switch (ioctl_num) {
698         case TE_IOCTL_OPEN_CLIENT_SESSION:
699         case TE_IOCTL_CLOSE_CLIENT_SESSION:
700         case TE_IOCTL_LAUNCH_OPERATION:
701                 mutex_lock(&smc_lock);
702                 err = te_handle_trustedapp_ioctl(file, ioctl_num, ioctl_param);
703                 mutex_unlock(&smc_lock);
704                 break;
705
706         case TE_IOCTL_OPEN_CLIENT_SESSION_COMPAT:
707         case TE_IOCTL_CLOSE_CLIENT_SESSION_COMPAT:
708         case TE_IOCTL_LAUNCH_OPERATION_COMPAT:
709                 mutex_lock(&smc_lock);
710                 err = te_handle_trustedapp_ioctl_compat(file, ioctl_num,
711                                                         ioctl_param);
712                 mutex_unlock(&smc_lock);
713                 break;
714
715         case TE_IOCTL_SS_NEW_REQ_LEGACY:
716         case TE_IOCTL_SS_REQ_COMPLETE_LEGACY:
717                 err = te_handle_ss_ioctl_legacy(file, ioctl_num, ioctl_param);
718                 break;
719
720         case TE_IOCTL_SS_NEW_REQ:
721         case TE_IOCTL_SS_REQ_COMPLETE:
722                 err = te_handle_ss_ioctl(file, ioctl_num, ioctl_param);
723                 break;
724
725         default:
726                 pr_err("%s: Invalid IOCTL (0x%x) id 0x%x max 0x%lx\n",
727                         __func__, ioctl_num, _IOC_NR(ioctl_num),
728                         (unsigned long)TE_IOCTL_MAX_NR);
729                 err = -EINVAL;
730                 break;
731         }
732
733         return err;
734 }
735
736 /*
737  * tlk_driver function definitions.
738  */
739 static const struct file_operations tlk_device_fops = {
740         .owner = THIS_MODULE,
741         .open = tlk_device_open,
742         .release = tlk_device_release,
743         .unlocked_ioctl = tlk_device_ioctl,
744 #ifdef CONFIG_COMPAT
745         .compat_ioctl = tlk_device_ioctl,
746 #endif
747 };
748
749 struct miscdevice tlk_misc_device = {
750         .minor = MISC_DYNAMIC_MINOR,
751         .name = "tlk_device",
752         .fops = &tlk_device_fops,
753 };
754
755 static int __init tlk_init(void)
756 {
757         int ret;
758
759         INIT_LIST_HEAD(&(tlk_dev.used_cmd_list));
760         INIT_LIST_HEAD(&(tlk_dev.free_cmd_list));
761
762         ret = te_create_free_cmd_list(&tlk_dev);
763         if (ret != 0)
764                 return ret;
765
766         return misc_register(&tlk_misc_device);
767 }
768
769 module_init(tlk_init);