First version
[tegra/ote_partner/tlk_driver.git] / ote_fs.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/slab.h>
20 #include <linux/syscalls.h>
21 #include <linux/list.h>
22 #include <linux/completion.h>
23 #include <linux/workqueue.h>
24 #include <linux/bitops.h>
25 #include <linux/uaccess.h>
26 #include <linux/dma-mapping.h>
27
28 #include "ote_protocol.h"
29
30 static DECLARE_COMPLETION(req_ready);
31 static DECLARE_COMPLETION(req_complete);
32
33 static struct te_ss_op *ss_op_shmem;
34 static uint32_t ss_op_size;
35
36 static void indicate_ss_op_complete(void)
37 {
38         tlk_generic_smc(TE_SMC_SS_REQ_COMPLETE, 0, 0);
39 }
40
41 int te_handle_ss_ioctl(struct file *file, unsigned int ioctl_num,
42         unsigned long ioctl_param)
43 {
44         switch (ioctl_num) {
45         case TE_IOCTL_SS_NEW_REQ:
46                 /* wait for a new request */
47                 if (wait_for_completion_interruptible(&req_ready))
48                         return -ENODATA;
49
50                 /* transfer pending request to daemon's buffer */
51                 if (copy_to_user((void __user *)ioctl_param, ss_op_shmem,
52                                         ss_op_size)) {
53                         pr_err("copy_to_user failed for new request\n");
54                         return -EFAULT;
55                 }
56                 break;
57
58         case TE_IOCTL_SS_REQ_COMPLETE: /* request complete */
59                 if (copy_from_user(ss_op_shmem, (void __user *)ioctl_param,
60                                         ss_op_size)) {
61                         pr_err("copy_from_user failed for request\n");
62                         return -EFAULT;
63                 }
64
65                 /* signal the producer */
66                 complete(&req_complete);
67                 break;
68         }
69
70         return 0;
71 }
72
73 void tlk_ss_op(uint32_t size)
74 {
75         /* store size of request */
76         ss_op_size = size;
77
78         /* signal consumer */
79         complete(&req_ready);
80
81         /* wait for the consumer's signal */
82         wait_for_completion(&req_complete);
83
84         /* signal completion to the secure world */
85         indicate_ss_op_complete();
86 }
87
88 static int __init tlk_ss_init(void)
89 {
90         dma_addr_t ss_op_shmem_dma;
91
92         /* allocate shared memory buffer */
93         ss_op_shmem = dma_alloc_coherent(NULL, sizeof(struct te_ss_op),
94                         &ss_op_shmem_dma, GFP_KERNEL);
95         if (!ss_op_shmem) {
96                 pr_err("%s: no memory available for fs operations\n", __func__);
97                 return -ENOMEM;
98         }
99
100         tlk_generic_smc(TE_SMC_SS_REGISTER_HANDLER,
101                         (uintptr_t)tlk_ss_op, (uintptr_t)ss_op_shmem);
102
103         return 0;
104 }
105
106 arch_initcall(tlk_ss_init);