blob: c2b6caaf8863e0663afa06036d0545dc86d01209 [file] [log] [blame]
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +01001/*
2 * Copyright (c) 2022 ARM Limited.
3 *
4 * This program is free software and is provided to you under the terms of the
5 * GNU General Public License version 2 as published by the Free Software
6 * Foundation, and any use by you of this program is subject to the terms
7 * of such GNU licence.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, you can access it online at
16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 *
18 * SPDX-License-Identifier: GPL-2.0-only
19 */
20
21/****************************************************************************
22 * Includes
23 ****************************************************************************/
24
25#include "ethosu_network_info.h"
26
27#include "ethosu_device.h"
28#include "ethosu_network.h"
29#include "ethosu_mailbox.h"
30#include "uapi/ethosu.h"
31
32/****************************************************************************
33 * Functions
34 ****************************************************************************/
35
36static void ethosu_network_info_destroy(struct kref *kref)
37{
38 struct ethosu_network_info *info =
39 container_of(kref, struct ethosu_network_info, kref);
40
41 dev_info(info->edev->dev, "Network info destroy. handle=0x%pK\n", info);
42
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010043 list_del(&info->msg.list);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +010044
45 ethosu_network_put(info->net);
46
47 devm_kfree(info->edev->dev, info);
48}
49
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +010050static int ethosu_network_info_send(struct ethosu_network_info *info)
51{
52 int ret;
53
54 /* Send network info request to firmware */
55 ret = ethosu_mailbox_network_info_request(&info->edev->mailbox,
56 info,
57 info->net->buf,
58 info->net->index);
59 if (ret)
60 return ret;
61
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010062 return 0;
63}
64
65static void ethosu_network_info_fail(struct ethosu_mailbox_msg *msg)
66{
67 struct ethosu_network_info *info =
68 container_of(msg, typeof(*info), msg);
69
70 if (completion_done(&info->done))
71 return;
72
73 info->errno = -EFAULT;
74 complete(&info->done);
75}
76
77static int ethosu_network_info_resend(struct ethosu_mailbox_msg *msg)
78{
79 struct ethosu_network_info *info =
80 container_of(msg, typeof(*info), msg);
81 int ret;
82
83 /* Don't resend request if response has already been received */
84 if (completion_done(&info->done))
85 return 0;
86
87 /* Resend request */
88 ret = ethosu_network_info_send(info);
89 if (ret)
90 return ret;
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +010091
92 return 0;
93}
94
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +010095struct ethosu_network_info *ethosu_network_info_create(
96 struct ethosu_device *edev,
97 struct ethosu_network *net,
98 struct ethosu_uapi_network_info *uapi)
99{
100 struct ethosu_network_info *info;
101 int ret;
102
103 info = devm_kzalloc(edev->dev, sizeof(*info), GFP_KERNEL);
104 if (!info)
105 return ERR_PTR(-ENOMEM);
106
107 info->edev = edev;
108 info->net = net;
109 info->uapi = uapi;
110 kref_init(&info->kref);
111 init_completion(&info->done);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100112 info->msg.fail = ethosu_network_info_fail;
113 info->msg.resend = ethosu_network_info_resend;
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100114
115 /* Insert network info to network info list */
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100116 list_add(&info->msg.list, &edev->mailbox.pending_list);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100117
118 /* Get reference to network */
119 ethosu_network_get(net);
120
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +0100121 ret = ethosu_network_info_send(info);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100122 if (ret)
123 goto put_info;
124
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100125 dev_info(edev->dev, "Network info create. handle=%p\n", info);
126
127 return info;
128
129put_info:
130 ethosu_network_info_put(info);
131
132 return ERR_PTR(ret);
133}
134
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100135void ethosu_network_info_get(struct ethosu_network_info *info)
136{
137 kref_get(&info->kref);
138}
139
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100140int ethosu_network_info_put(struct ethosu_network_info *info)
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100141{
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100142 return kref_put(&info->kref, ethosu_network_info_destroy);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100143}
144
145int ethosu_network_info_wait(struct ethosu_network_info *info,
146 int timeout_ms)
147{
148 int timeout;
149
150 timeout = wait_for_completion_timeout(&info->done,
151 msecs_to_jiffies(timeout_ms));
152
153 if (!timeout) {
154 dev_warn(info->edev->dev,
155 "Network info timed out.");
156
157 return -ETIME;
158 }
159
160 return info->errno;
161}
162
163void ethosu_network_info_rsp(struct ethosu_device *edev,
164 struct ethosu_core_network_info_rsp *rsp)
165{
166 struct ethosu_network_info *info =
167 (struct ethosu_network_info *)rsp->user_arg;
168 uint32_t i;
169 int ret;
170
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100171 ret = ethosu_mailbox_find(&edev->mailbox, &info->msg);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100172 if (0 != ret) {
173 dev_warn(edev->dev,
174 "Handle not found in network info list. handle=0x%p\n",
175 info);
176
177 return;
178 }
179
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100180 if (completion_done(&info->done))
181 return;
182
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100183 info->errno = 0;
184
185 if (rsp->status != ETHOSU_CORE_STATUS_OK) {
186 info->errno = -EBADF;
187 goto signal_complete;
188 }
189
190 if (rsp->ifm_count > ETHOSU_FD_MAX || rsp->ofm_count > ETHOSU_FD_MAX) {
191 info->errno = -ENFILE;
192 goto signal_complete;
193 }
194
195 strncpy(info->uapi->desc, rsp->desc, sizeof(info->uapi->desc));
196
197 info->uapi->ifm_count = rsp->ifm_count;
198 for (i = 0; i < rsp->ifm_count; i++)
199 info->uapi->ifm_size[i] = rsp->ifm_size[i];
200
201 info->uapi->ofm_count = rsp->ofm_count;
202 for (i = 0; i < rsp->ofm_count; i++)
203 info->uapi->ofm_size[i] = rsp->ofm_size[i];
204
205signal_complete:
206 complete(&info->done);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100207}