blob: 38d7db225381abf7cd4808d7da34844a090bc0a3 [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
Ledion Dajaedd25502023-10-17 09:15:32 +0200111 dev_dbg(dev, "Network ioctl: Network info. net=0x%pK\n", 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))) {
125 ret = -EFAULT;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200126 break;
Mikael Olsson891156d2023-08-24 13:20:31 +0200127 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200128
Ledion Dajaedd25502023-10-17 09:15:32 +0200129 dev_dbg(dev,
130 "Network ioctl: Inference. ifm_fd=%u, ofm_fd=%u\n",
131 uapi.ifm_fd[0], uapi.ofm_fd[0]);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200132
Mikael Olsson16be2852024-02-12 09:56:56 +0100133 ret = ethosu_rpmsg_inference_create(dev, net->mailbox, net,
134 &uapi);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200135 break;
136 }
137 default: {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100138 dev_err(dev, "Invalid ioctl. cmd=%u, arg=%lu",
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200139 cmd, arg);
Mikael Olsson891156d2023-08-24 13:20:31 +0200140 ret = -ENOIOCTLCMD;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200141 break;
142 }
143 }
144
Kristofer Jonssonec477042023-01-20 13:38:13 +0100145 device_unlock(net->dev);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200146
147 return ret;
148}
149
Mikael Olsson16be2852024-02-12 09:56:56 +0100150int ethosu_rpmsg_network_create(struct device *dev,
151 struct ethosu_rpmsg_mailbox *mailbox,
152 struct ethosu_uapi_network_create *uapi)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200153{
Mikael Olsson16be2852024-02-12 09:56:56 +0100154 struct ethosu_rpmsg_network *net;
Mikael Olssonc081e592023-10-30 11:10:56 +0100155 const void __user *data;
156 int ret;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200157
Kristofer Jonssonec477042023-01-20 13:38:13 +0100158 net = devm_kzalloc(dev, sizeof(*net), GFP_KERNEL);
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100159 if (!net)
160 return -ENOMEM;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200161
Kristofer Jonssonec477042023-01-20 13:38:13 +0100162 net->dev = dev;
163 net->mailbox = mailbox;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200164 kref_init(&net->kref);
165
Mikael Olsson45d47992023-10-12 15:32:56 +0200166 switch (uapi->type) {
Mikael Olssonc081e592023-10-30 11:10:56 +0100167 case ETHOSU_UAPI_NETWORK_USER_BUFFER:
168 if (!uapi->network.data_ptr) {
169 dev_err(dev, "Invalid network data ptr\n");
170 ret = -EINVAL;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100171 goto free_net;
172 }
Mikael Olsson45d47992023-10-12 15:32:56 +0200173
Mikael Olssonc081e592023-10-30 11:10:56 +0100174 if (!uapi->network.size) {
175 dev_err(dev, "Invalid network data size\n");
176 ret = -EINVAL;
177 goto free_net;
178 }
179
180 net->dma_mem = ethosu_dma_mem_alloc(dev, uapi->network.size);
181 if (IS_ERR(net->dma_mem)) {
182 ret = PTR_ERR(net->dma_mem);
183 goto free_net;
184 }
185
186 data = u64_to_user_ptr(uapi->network.data_ptr);
187 ret = copy_from_user(net->dma_mem->cpu_addr, data,
188 uapi->network.size);
189 if (ret)
190 goto free_dma_mem;
191
Mikael Olsson45d47992023-10-12 15:32:56 +0200192 break;
193 case ETHOSU_UAPI_NETWORK_INDEX:
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100194 net->index = uapi->index;
Mikael Olsson45d47992023-10-12 15:32:56 +0200195 break;
196 default:
197 ret = -EINVAL;
198 goto free_net;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100199 }
200
Mikael Olsson16be2852024-02-12 09:56:56 +0100201 ret = anon_inode_getfd("ethosu-network", &ethosu_rpmsg_network_fops,
202 net,
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200203 O_RDWR | O_CLOEXEC);
204 if (ret < 0)
Mikael Olssonc081e592023-10-30 11:10:56 +0100205 goto free_dma_mem;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200206
207 net->file = fget(ret);
208 fput(net->file);
209
Ledion Dajaedd25502023-10-17 09:15:32 +0200210 dev_dbg(dev,
211 "Network create. file=0x%pK, fd=%d, net=0x%pK, buf=0x%pK, index=%u",
Mikael Olssonc081e592023-10-30 11:10:56 +0100212 net->file, ret, net, net->dma_mem, net->index);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200213
214 return ret;
215
Mikael Olssonc081e592023-10-30 11:10:56 +0100216free_dma_mem:
217 if (net->dma_mem != NULL)
218 ethosu_dma_mem_free(&net->dma_mem);
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100219
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200220free_net:
Mikael Olsson1182f382023-08-10 13:25:44 +0200221 memset(net, 0, sizeof(*net));
Kristofer Jonssonec477042023-01-20 13:38:13 +0100222 devm_kfree(dev, net);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200223
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200224 return ret;
225}
226
Mikael Olsson16be2852024-02-12 09:56:56 +0100227struct ethosu_rpmsg_network *ethosu_rpmsg_network_get_from_fd(int fd)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200228{
Mikael Olsson16be2852024-02-12 09:56:56 +0100229 struct ethosu_rpmsg_network *net;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200230 struct file *file;
231
232 file = fget(fd);
233 if (!file)
234 return ERR_PTR(-EINVAL);
235
Mikael Olsson16be2852024-02-12 09:56:56 +0100236 if (!ethosu_rpmsg_network_verify(file)) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200237 fput(file);
238
239 return ERR_PTR(-EINVAL);
240 }
241
242 net = file->private_data;
Mikael Olsson16be2852024-02-12 09:56:56 +0100243 ethosu_rpmsg_network_get(net);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200244 fput(file);
245
246 return net;
247}
248
Mikael Olsson16be2852024-02-12 09:56:56 +0100249void ethosu_rpmsg_network_get(struct ethosu_rpmsg_network *net)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200250{
251 kref_get(&net->kref);
252}
253
Mikael Olsson16be2852024-02-12 09:56:56 +0100254int ethosu_rpmsg_network_put(struct ethosu_rpmsg_network *net)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200255{
Mikael Olsson16be2852024-02-12 09:56:56 +0100256 return kref_put(&net->kref, ethosu_rpmsg_network_destroy);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200257}