blob: cf36f2d04fb393c76c61a3dbfa863344db065f5a [file] [log] [blame]
Kristofer Jonsson116a6352020-08-20 17:25:23 +02001/*
Mikael Olssond4ad9e52024-02-07 11:22:26 +01002 * SPDX-FileCopyrightText: Copyright 2020, 2022-2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
Ledion Dajaedd25502023-10-17 09:15:32 +02003 * SPDX-License-Identifier: GPL-2.0-only
Kristofer Jonsson116a6352020-08-20 17:25:23 +02004 *
5 * This program is free software and is provided to you under the terms of the
6 * GNU General Public License version 2 as published by the Free Software
7 * Foundation, and any use by you of this program is subject to the terms
8 * of such GNU licence.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, you can access it online at
17 * http://www.gnu.org/licenses/gpl-2.0.html.
Kristofer Jonsson116a6352020-08-20 17:25:23 +020018 */
19
20/****************************************************************************
21 * Includes
22 ****************************************************************************/
23
Mikael Olssond4ad9e52024-02-07 11:22:26 +010024#include <rpmsg/ethosu_rpmsg_network.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020025
Mikael Olssond4ad9e52024-02-07 11:22:26 +010026#include <common/ethosu_device.h>
27#include <common/ethosu_dma_mem.h>
28#include <rpmsg/ethosu_rpmsg_inference.h>
29#include <rpmsg/ethosu_rpmsg_network_info.h>
30#include <uapi/ethosu.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020031
32#include <linux/anon_inodes.h>
33#include <linux/file.h>
34#include <linux/fs.h>
35#include <linux/uaccess.h>
36
37/****************************************************************************
38 * Variables
39 ****************************************************************************/
40
Mikael Olsson16be2852024-02-12 09:56:56 +010041static int ethosu_rpmsg_network_release(struct inode *inode,
42 struct file *file);
Kristofer Jonsson116a6352020-08-20 17:25:23 +020043
Mikael Olsson16be2852024-02-12 09:56:56 +010044static long ethosu_rpmsg_network_ioctl(struct file *file,
45 unsigned int cmd,
46 unsigned long arg);
Kristofer Jonsson116a6352020-08-20 17:25:23 +020047
Mikael Olsson16be2852024-02-12 09:56:56 +010048static const struct file_operations ethosu_rpmsg_network_fops = {
49 .release = &ethosu_rpmsg_network_release,
50 .unlocked_ioctl = &ethosu_rpmsg_network_ioctl,
Kristofer Jonsson116a6352020-08-20 17:25:23 +020051#ifdef CONFIG_COMPAT
Mikael Olsson16be2852024-02-12 09:56:56 +010052 .compat_ioctl = &ethosu_rpmsg_network_ioctl,
Kristofer Jonsson116a6352020-08-20 17:25:23 +020053#endif
54};
55
56/****************************************************************************
57 * Functions
58 ****************************************************************************/
59
Mikael Olsson16be2852024-02-12 09:56:56 +010060static bool ethosu_rpmsg_network_verify(struct file *file)
Kristofer Jonsson116a6352020-08-20 17:25:23 +020061{
Mikael Olsson16be2852024-02-12 09:56:56 +010062 return file->f_op == &ethosu_rpmsg_network_fops;
Kristofer Jonsson116a6352020-08-20 17:25:23 +020063}
64
Mikael Olsson16be2852024-02-12 09:56:56 +010065static void ethosu_rpmsg_network_destroy(struct kref *kref)
Kristofer Jonsson116a6352020-08-20 17:25:23 +020066{
Mikael Olsson16be2852024-02-12 09:56:56 +010067 struct ethosu_rpmsg_network *net =
68 container_of(kref, struct ethosu_rpmsg_network, kref);
Kristofer Jonssonec477042023-01-20 13:38:13 +010069 struct device *dev = net->dev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +020070
Ledion Dajaedd25502023-10-17 09:15:32 +020071 dev_dbg(dev, "Network destroy. net=0x%pK\n", net);
Kristofer Jonsson116a6352020-08-20 17:25:23 +020072
Mikael Olssonc081e592023-10-30 11:10:56 +010073 if (net->dma_mem != NULL)
74 ethosu_dma_mem_free(&net->dma_mem);
Kristofer Jonsson35de9e62022-03-08 13:25:45 +010075
Mikael Olsson1182f382023-08-10 13:25:44 +020076 memset(net, 0, sizeof(*net));
Kristofer Jonssonec477042023-01-20 13:38:13 +010077 devm_kfree(dev, net);
Kristofer Jonsson116a6352020-08-20 17:25:23 +020078}
79
Mikael Olsson16be2852024-02-12 09:56:56 +010080static int ethosu_rpmsg_network_release(struct inode *inode,
81 struct file *file)
Kristofer Jonsson116a6352020-08-20 17:25:23 +020082{
Mikael Olsson16be2852024-02-12 09:56:56 +010083 struct ethosu_rpmsg_network *net = file->private_data;
Kristofer Jonssonec477042023-01-20 13:38:13 +010084 struct device *dev = net->dev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +020085
Ledion Dajaedd25502023-10-17 09:15:32 +020086 dev_dbg(dev, "Network release. file=0x%pK, net=0x%pK\n",
87 file, net);
Kristofer Jonsson116a6352020-08-20 17:25:23 +020088
Mikael Olsson16be2852024-02-12 09:56:56 +010089 ethosu_rpmsg_network_put(net);
Kristofer Jonsson116a6352020-08-20 17:25:23 +020090
91 return 0;
92}
93
Mikael Olsson16be2852024-02-12 09:56:56 +010094static long ethosu_rpmsg_network_ioctl(struct file *file,
95 unsigned int cmd,
96 unsigned long arg)
Kristofer Jonsson116a6352020-08-20 17:25:23 +020097{
Mikael Olsson16be2852024-02-12 09:56:56 +010098 struct ethosu_rpmsg_network *net = file->private_data;
Kristofer Jonssonec477042023-01-20 13:38:13 +010099 struct device *dev = net->dev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200100 void __user *udata = (void __user *)arg;
Mikael Olsson891156d2023-08-24 13:20:31 +0200101 int ret;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200102
Kristofer Jonssonec477042023-01-20 13:38:13 +0100103 ret = device_lock_interruptible(net->dev);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200104 if (ret)
105 return ret;
106
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200107 switch (cmd) {
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100108 case ETHOSU_IOCTL_NETWORK_INFO: {
Mikael Olssonec902232023-08-24 13:28:19 +0200109 struct ethosu_uapi_network_info uapi = { 0 };
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100110
Mikael Olssond80345f2024-04-04 17:28:52 +0200111 dev_dbg(dev, "Network ioctl: Network info. net=0x%pK", net);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100112
Mikael Olsson16be2852024-02-12 09:56:56 +0100113 ret = ethosu_rpmsg_network_info_request(dev, net->mailbox, net,
114 &uapi);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100115 if (ret)
116 break;
117
118 ret = copy_to_user(udata, &uapi, sizeof(uapi)) ? -EFAULT : 0;
119 break;
120 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200121 case ETHOSU_IOCTL_INFERENCE_CREATE: {
122 struct ethosu_uapi_inference_create uapi;
123
Mikael Olsson891156d2023-08-24 13:20:31 +0200124 if (copy_from_user(&uapi, udata, sizeof(uapi))) {
Mikael Olssond80345f2024-04-04 17:28:52 +0200125 dev_err(dev,
126 "Network ioctl: Failed to copy inference request");
Mikael Olsson891156d2023-08-24 13:20:31 +0200127 ret = -EFAULT;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200128 break;
Mikael Olsson891156d2023-08-24 13:20:31 +0200129 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200130
Ledion Dajaedd25502023-10-17 09:15:32 +0200131 dev_dbg(dev,
Mikael Olssond80345f2024-04-04 17:28:52 +0200132 "Network ioctl: Inference. ifm_fd=%u, ofm_fd=%u",
Ledion Dajaedd25502023-10-17 09:15:32 +0200133 uapi.ifm_fd[0], uapi.ofm_fd[0]);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200134
Mikael Olsson16be2852024-02-12 09:56:56 +0100135 ret = ethosu_rpmsg_inference_create(dev, net->mailbox, net,
136 &uapi);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200137 break;
138 }
139 default: {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100140 dev_err(dev, "Invalid ioctl. cmd=%u, arg=%lu",
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200141 cmd, arg);
Mikael Olsson891156d2023-08-24 13:20:31 +0200142 ret = -ENOIOCTLCMD;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200143 break;
144 }
145 }
146
Kristofer Jonssonec477042023-01-20 13:38:13 +0100147 device_unlock(net->dev);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200148
149 return ret;
150}
151
Mikael Olsson16be2852024-02-12 09:56:56 +0100152int ethosu_rpmsg_network_create(struct device *dev,
153 struct ethosu_rpmsg_mailbox *mailbox,
154 struct ethosu_uapi_network_create *uapi)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200155{
Mikael Olsson16be2852024-02-12 09:56:56 +0100156 struct ethosu_rpmsg_network *net;
Mikael Olssonc081e592023-10-30 11:10:56 +0100157 const void __user *data;
158 int ret;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200159
Kristofer Jonssonec477042023-01-20 13:38:13 +0100160 net = devm_kzalloc(dev, sizeof(*net), GFP_KERNEL);
Mikael Olssond80345f2024-04-04 17:28:52 +0200161 if (!net) {
162 dev_err(dev, "Network create. Failed to allocate struct");
163
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100164 return -ENOMEM;
Mikael Olssond80345f2024-04-04 17:28:52 +0200165 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200166
Kristofer Jonssonec477042023-01-20 13:38:13 +0100167 net->dev = dev;
168 net->mailbox = mailbox;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200169 kref_init(&net->kref);
170
Mikael Olsson45d47992023-10-12 15:32:56 +0200171 switch (uapi->type) {
Mikael Olssonc081e592023-10-30 11:10:56 +0100172 case ETHOSU_UAPI_NETWORK_USER_BUFFER:
173 if (!uapi->network.data_ptr) {
Mikael Olssond80345f2024-04-04 17:28:52 +0200174 dev_err(dev,
175 "Network create. Invalid network data ptr");
Mikael Olssonc081e592023-10-30 11:10:56 +0100176 ret = -EINVAL;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100177 goto free_net;
178 }
Mikael Olsson45d47992023-10-12 15:32:56 +0200179
Mikael Olssonc081e592023-10-30 11:10:56 +0100180 if (!uapi->network.size) {
Mikael Olssond80345f2024-04-04 17:28:52 +0200181 dev_err(dev,
182 "Network create. Invalid network data size");
Mikael Olssonc081e592023-10-30 11:10:56 +0100183 ret = -EINVAL;
184 goto free_net;
185 }
186
187 net->dma_mem = ethosu_dma_mem_alloc(dev, uapi->network.size);
188 if (IS_ERR(net->dma_mem)) {
189 ret = PTR_ERR(net->dma_mem);
Mikael Olssond80345f2024-04-04 17:28:52 +0200190 dev_err(dev,
191 "Network create. Failed to allocate DMA memory. ret=%d",
192 ret);
Mikael Olssonc081e592023-10-30 11:10:56 +0100193 goto free_net;
194 }
195
196 data = u64_to_user_ptr(uapi->network.data_ptr);
197 ret = copy_from_user(net->dma_mem->cpu_addr, data,
198 uapi->network.size);
Mikael Olssond80345f2024-04-04 17:28:52 +0200199 if (ret) {
200 dev_err(dev,
201 "Network create. Failed to copy network data from user buffer. ret=%d",
202 ret);
Mikael Olssonc081e592023-10-30 11:10:56 +0100203 goto free_dma_mem;
Mikael Olssond80345f2024-04-04 17:28:52 +0200204 }
Mikael Olssonc081e592023-10-30 11:10:56 +0100205
Mikael Olsson45d47992023-10-12 15:32:56 +0200206 break;
207 case ETHOSU_UAPI_NETWORK_INDEX:
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100208 net->index = uapi->index;
Mikael Olsson45d47992023-10-12 15:32:56 +0200209 break;
210 default:
Mikael Olssond80345f2024-04-04 17:28:52 +0200211 dev_err(dev, "Network create. Invalid buffer type. type=%u",
212 uapi->type);
Mikael Olsson45d47992023-10-12 15:32:56 +0200213 ret = -EINVAL;
214 goto free_net;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100215 }
216
Mikael Olsson16be2852024-02-12 09:56:56 +0100217 ret = anon_inode_getfd("ethosu-network", &ethosu_rpmsg_network_fops,
218 net,
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200219 O_RDWR | O_CLOEXEC);
Mikael Olssond80345f2024-04-04 17:28:52 +0200220 if (ret < 0) {
221 dev_err(dev,
222 "Network create. Failed to get file descriptor. ret=%d",
223 ret);
Mikael Olssonc081e592023-10-30 11:10:56 +0100224 goto free_dma_mem;
Mikael Olssond80345f2024-04-04 17:28:52 +0200225 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200226
227 net->file = fget(ret);
228 fput(net->file);
229
Ledion Dajaedd25502023-10-17 09:15:32 +0200230 dev_dbg(dev,
231 "Network create. file=0x%pK, fd=%d, net=0x%pK, buf=0x%pK, index=%u",
Mikael Olssonc081e592023-10-30 11:10:56 +0100232 net->file, ret, net, net->dma_mem, net->index);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200233
234 return ret;
235
Mikael Olssonc081e592023-10-30 11:10:56 +0100236free_dma_mem:
237 if (net->dma_mem != NULL)
238 ethosu_dma_mem_free(&net->dma_mem);
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100239
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200240free_net:
Mikael Olsson1182f382023-08-10 13:25:44 +0200241 memset(net, 0, sizeof(*net));
Kristofer Jonssonec477042023-01-20 13:38:13 +0100242 devm_kfree(dev, net);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200243
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200244 return ret;
245}
246
Mikael Olsson16be2852024-02-12 09:56:56 +0100247struct ethosu_rpmsg_network *ethosu_rpmsg_network_get_from_fd(int fd)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200248{
Mikael Olsson16be2852024-02-12 09:56:56 +0100249 struct ethosu_rpmsg_network *net;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200250 struct file *file;
251
252 file = fget(fd);
253 if (!file)
254 return ERR_PTR(-EINVAL);
255
Mikael Olsson16be2852024-02-12 09:56:56 +0100256 if (!ethosu_rpmsg_network_verify(file)) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200257 fput(file);
258
259 return ERR_PTR(-EINVAL);
260 }
261
262 net = file->private_data;
Mikael Olsson16be2852024-02-12 09:56:56 +0100263 ethosu_rpmsg_network_get(net);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200264 fput(file);
265
266 return net;
267}
268
Mikael Olsson16be2852024-02-12 09:56:56 +0100269void ethosu_rpmsg_network_get(struct ethosu_rpmsg_network *net)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200270{
271 kref_get(&net->kref);
272}
273
Mikael Olsson16be2852024-02-12 09:56:56 +0100274int ethosu_rpmsg_network_put(struct ethosu_rpmsg_network *net)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200275{
Mikael Olsson16be2852024-02-12 09:56:56 +0100276 return kref_put(&net->kref, ethosu_rpmsg_network_destroy);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200277}