[FOSS_TLK]security: tlk_driver: add daemon recovery support
[tegra/ote_partner/tlk_driver.git] / security / tlk_driver / ote_fs.c
1 /*
2  * Copyright (c) 2013-2015 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
35 static void tlk_ss_reset(void)
36 {
37         /* reset completion vars to default state */
38         INIT_COMPLETION(req_ready);
39         INIT_COMPLETION(req_complete);
40 }
41
42 int te_handle_ss_ioctl(struct file *file, unsigned int ioctl_num,
43         unsigned long ioctl_param)
44 {
45         int ss_cmd;
46
47         if (ioctl_num != TE_IOCTL_SS_CMD)
48                 return -EINVAL;
49
50         if (copy_from_user(&ss_cmd, (void __user *)ioctl_param,
51                                 sizeof(ss_cmd))) {
52                 pr_err("%s: copy from user space failed\n", __func__);
53                 return -EFAULT;
54         }
55
56         switch (ss_cmd) {
57         case TE_IOCTL_SS_CMD_GET_NEW_REQ:
58                 /* wait for a new request */
59                 if (wait_for_completion_interruptible(&req_ready))
60                         return -ENODATA;
61                 break;
62         case TE_IOCTL_SS_CMD_REQ_COMPLETE:
63                 /* signal the producer */
64                 complete(&req_complete);
65                 break;
66         default:
67                 pr_err("%s: unknown ss_cmd 0x%x\n", __func__, ss_cmd);
68                 return -EINVAL;
69         }
70
71         return 0;
72 }
73
74 int tlk_ss_op(void)
75 {
76         /* signal consumer */
77         complete(&req_ready);
78
79         /* wait for the consumer's signal */
80         if (!wait_for_completion_timeout(&req_complete,
81                                                 msecs_to_jiffies(5000))) {
82                 /* daemon didn't respond */
83                 tlk_ss_reset();
84                 return OTE_ERROR_CANCEL;
85         }
86
87         return OTE_SUCCESS;
88 }
89
90 static int __init tlk_ss_init(void)
91 {
92         dma_addr_t ss_op_shmem_dma;
93         int ret;
94
95         /* storage disabled? */
96         ret = ote_property_is_disabled("storage");
97         if (ret) {
98                 pr_err("%s: fail (%d)\n", __func__, ret);
99                 return ret;
100         }
101
102         /* allocate shared memory buffer */
103         ss_op_shmem = dma_alloc_coherent(NULL, sizeof(struct te_ss_op),
104                         &ss_op_shmem_dma, GFP_KERNEL);
105         if (!ss_op_shmem) {
106                 pr_err("%s: no memory available for fs operations\n", __func__);
107                 return -ENOMEM;
108         }
109
110         ret = send_smc(TE_SMC_SS_REGISTER_HANDLER,
111                         (uintptr_t)ss_op_shmem, 0);
112         if (ret != 0) {
113                 dma_free_coherent(NULL, sizeof(struct te_ss_op),
114                         (void *)ss_op_shmem, ss_op_shmem_dma);
115                 ss_op_shmem = NULL;
116                 return -ENOTSUPP;
117         }
118
119         return 0;
120 }
121
122 arch_initcall(tlk_ss_init);