blob: f7871defaeebe4c8bee929523c81c3ff32839960 [file] [log] [blame]
Kristofer Jonsson116a6352020-08-20 17:25:23 +02001/*
Ledion Dajaedd25502023-10-17 09:15:32 +02002 * SPDX-FileCopyrightText: Copyright 2020,2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
3 * 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
24#include "ethosu_network.h"
25
26#include "ethosu_buffer.h"
27#include "ethosu_device.h"
28#include "ethosu_inference.h"
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +010029#include "ethosu_network_info.h"
Kristofer Jonsson116a6352020-08-20 17:25:23 +020030#include "uapi/ethosu.h"
31
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
41static int ethosu_network_release(struct inode *inode,
42 struct file *file);
43
44static long ethosu_network_ioctl(struct file *file,
45 unsigned int cmd,
46 unsigned long arg);
47
48static const struct file_operations ethosu_network_fops = {
49 .release = &ethosu_network_release,
50 .unlocked_ioctl = &ethosu_network_ioctl,
51#ifdef CONFIG_COMPAT
52 .compat_ioctl = &ethosu_network_ioctl,
53#endif
54};
55
56/****************************************************************************
57 * Functions
58 ****************************************************************************/
59
60static bool ethosu_network_verify(struct file *file)
61{
62 return file->f_op == &ethosu_network_fops;
63}
64
65static void ethosu_network_destroy(struct kref *kref)
66{
67 struct ethosu_network *net =
68 container_of(kref, struct ethosu_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
Kristofer Jonsson35de9e62022-03-08 13:25:45 +010073 if (net->buf != NULL)
74 ethosu_buffer_put(net->buf);
75
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
80static int ethosu_network_release(struct inode *inode,
81 struct file *file)
82{
83 struct ethosu_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
89 ethosu_network_put(net);
90
91 return 0;
92}
93
94static long ethosu_network_ioctl(struct file *file,
95 unsigned int cmd,
96 unsigned long arg)
97{
98 struct ethosu_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 Olsson52c563d2023-08-24 13:28:35 +0200113 ret = ethosu_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
Kristofer Jonssonec477042023-01-20 13:38:13 +0100133 ret = ethosu_inference_create(dev, net->mailbox, net, &uapi);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200134 break;
135 }
136 default: {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100137 dev_err(dev, "Invalid ioctl. cmd=%u, arg=%lu",
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200138 cmd, arg);
Mikael Olsson891156d2023-08-24 13:20:31 +0200139 ret = -ENOIOCTLCMD;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200140 break;
141 }
142 }
143
Kristofer Jonssonec477042023-01-20 13:38:13 +0100144 device_unlock(net->dev);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200145
146 return ret;
147}
148
Kristofer Jonssonec477042023-01-20 13:38:13 +0100149int ethosu_network_create(struct device *dev,
150 struct ethosu_mailbox *mailbox,
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200151 struct ethosu_uapi_network_create *uapi)
152{
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200153 struct ethosu_network *net;
154 int ret = -ENOMEM;
155
Kristofer Jonssonec477042023-01-20 13:38:13 +0100156 net = devm_kzalloc(dev, sizeof(*net), GFP_KERNEL);
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100157 if (!net)
158 return -ENOMEM;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200159
Kristofer Jonssonec477042023-01-20 13:38:13 +0100160 net->dev = dev;
161 net->mailbox = mailbox;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100162 net->buf = NULL;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200163 kref_init(&net->kref);
164
Mikael Olsson45d47992023-10-12 15:32:56 +0200165 switch (uapi->type) {
166 case ETHOSU_UAPI_NETWORK_BUFFER:
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100167 net->buf = ethosu_buffer_get_from_fd(uapi->fd);
168 if (IS_ERR(net->buf)) {
169 ret = PTR_ERR(net->buf);
170 goto free_net;
171 }
Mikael Olsson45d47992023-10-12 15:32:56 +0200172
173 break;
174 case ETHOSU_UAPI_NETWORK_INDEX:
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100175 net->index = uapi->index;
Mikael Olsson45d47992023-10-12 15:32:56 +0200176 break;
177 default:
178 ret = -EINVAL;
179 goto free_net;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100180 }
181
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200182 ret = anon_inode_getfd("ethosu-network", &ethosu_network_fops, net,
183 O_RDWR | O_CLOEXEC);
184 if (ret < 0)
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100185 goto put_buf;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200186
187 net->file = fget(ret);
188 fput(net->file);
189
Ledion Dajaedd25502023-10-17 09:15:32 +0200190 dev_dbg(dev,
191 "Network create. file=0x%pK, fd=%d, net=0x%pK, buf=0x%pK, index=%u",
192 net->file, ret, net, net->buf, net->index);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200193
194 return ret;
195
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100196put_buf:
197 if (net->buf != NULL)
198 ethosu_buffer_put(net->buf);
199
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200200free_net:
Mikael Olsson1182f382023-08-10 13:25:44 +0200201 memset(net, 0, sizeof(*net));
Kristofer Jonssonec477042023-01-20 13:38:13 +0100202 devm_kfree(dev, net);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200203
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200204 return ret;
205}
206
207struct ethosu_network *ethosu_network_get_from_fd(int fd)
208{
209 struct ethosu_network *net;
210 struct file *file;
211
212 file = fget(fd);
213 if (!file)
214 return ERR_PTR(-EINVAL);
215
216 if (!ethosu_network_verify(file)) {
217 fput(file);
218
219 return ERR_PTR(-EINVAL);
220 }
221
222 net = file->private_data;
223 ethosu_network_get(net);
224 fput(file);
225
226 return net;
227}
228
229void ethosu_network_get(struct ethosu_network *net)
230{
231 kref_get(&net->kref);
232}
233
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100234int ethosu_network_put(struct ethosu_network *net)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200235{
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100236 return kref_put(&net->kref, ethosu_network_destroy);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200237}