blob: e2acb22b41509459b4a57de974c61c272471a174 [file] [log] [blame]
Davide Grohmann7e8f5082022-03-23 12:48:45 +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_cancel_inference.h"
26
27#include "ethosu_core_interface.h"
28#include "ethosu_device.h"
29#include "ethosu_inference.h"
30
31#include <linux/wait.h>
32
33/****************************************************************************
34 * Defines
35 ****************************************************************************/
36
37#define CANCEL_INFERENCE_RESP_TIMEOUT_MS 2000
38
39/****************************************************************************
40 * Functions
41 ****************************************************************************/
42
Davide Grohmann7e8f5082022-03-23 12:48:45 +010043static int ethosu_cancel_inference_send(
44 struct ethosu_cancel_inference *cancellation)
45{
46 return ethosu_mailbox_cancel_inference(&cancellation->edev->mailbox,
Davide Grohmann32660f92022-04-27 16:49:07 +020047 &cancellation->msg,
48 cancellation->inf->msg.id);
Davide Grohmann7e8f5082022-03-23 12:48:45 +010049}
50
51static void ethosu_cancel_inference_fail(struct ethosu_mailbox_msg *msg)
52{
53 struct ethosu_cancel_inference *cancellation =
54 container_of(msg, typeof(*cancellation), msg);
55
56 if (completion_done(&cancellation->done))
57 return;
58
59 cancellation->errno = -EFAULT;
60 cancellation->uapi->status = ETHOSU_UAPI_STATUS_ERROR;
61 complete(&cancellation->done);
62}
63
64static int ethosu_cancel_inference_complete(struct ethosu_mailbox_msg *msg)
65{
66 struct ethosu_cancel_inference *cancellation =
67 container_of(msg, typeof(*cancellation), msg);
68
69 if (completion_done(&cancellation->done))
70 return 0;
71
72 cancellation->errno = 0;
73 cancellation->uapi->status =
74 cancellation->inf->done &&
75 cancellation->inf->status != ETHOSU_UAPI_STATUS_OK ?
76 ETHOSU_UAPI_STATUS_OK :
77 ETHOSU_UAPI_STATUS_ERROR;
78 complete(&cancellation->done);
79
80 return 0;
81}
82
83int ethosu_cancel_inference_request(struct ethosu_inference *inf,
84 struct ethosu_uapi_cancel_inference_status *uapi)
85{
86 struct ethosu_cancel_inference *cancellation;
87 int ret;
88 int timeout;
89
90 if (inf->done) {
91 uapi->status = ETHOSU_UAPI_STATUS_ERROR;
92
93 return 0;
94 }
95
96 cancellation =
97 devm_kzalloc(inf->edev->dev,
98 sizeof(struct ethosu_cancel_inference),
99 GFP_KERNEL);
100 if (!cancellation)
101 return -ENOMEM;
102
103 /* increase ref count on the inference we are refering to */
104 ethosu_inference_get(inf);
105 /* mark inference ABORTING to avoid resending the inference message */
106 inf->status = ETHOSU_CORE_STATUS_ABORTING;
107
108 cancellation->edev = inf->edev;
109 cancellation->inf = inf;
110 cancellation->uapi = uapi;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100111 init_completion(&cancellation->done);
112 cancellation->msg.fail = ethosu_cancel_inference_fail;
113
114 /* Never resend messages but always complete, since we have restart the
115 * whole firmware and marked the inference as aborted */
116 cancellation->msg.resend = ethosu_cancel_inference_complete;
117
Davide Grohmann32660f92022-04-27 16:49:07 +0200118 ret = ethosu_mailbox_register(&cancellation->edev->mailbox,
119 &cancellation->msg);
120 if (ret < 0)
121 goto kfree;
122
123 dev_info(cancellation->edev->dev,
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200124 "Inference cancellation create. cancel=0x%pK, msg.id=%d\n",
125 cancellation, cancellation->msg.id);
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100126
127 ret = ethosu_cancel_inference_send(cancellation);
128 if (0 != ret)
Davide Grohmann32660f92022-04-27 16:49:07 +0200129 goto deregister;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100130
131 /* Unlock the mutex before going to block on the condition */
132 mutex_unlock(&cancellation->edev->mutex);
133 /* wait for response to arrive back */
134 timeout = wait_for_completion_timeout(&cancellation->done,
135 msecs_to_jiffies(
136 CANCEL_INFERENCE_RESP_TIMEOUT_MS));
137 /* take back the mutex before resuming to do anything */
138 ret = mutex_lock_interruptible(&cancellation->edev->mutex);
139 if (0 != ret)
Davide Grohmann32660f92022-04-27 16:49:07 +0200140 goto deregister;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100141
142 if (0 == timeout /* timed out*/) {
143 dev_warn(inf->edev->dev,
144 "Msg: Cancel Inference response lost - timeout\n");
145 ret = -EIO;
Davide Grohmann32660f92022-04-27 16:49:07 +0200146 goto deregister;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100147 }
148
149 if (cancellation->errno) {
150 ret = cancellation->errno;
Davide Grohmann32660f92022-04-27 16:49:07 +0200151 goto deregister;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100152 }
153
Davide Grohmann8b1fe552022-04-07 16:58:32 +0200154 /* if cancellation failed and the inference did not complete then reset
155 * the firmware */
156 if (cancellation->uapi->status == ETHOSU_UAPI_STATUS_ERROR &&
157 !cancellation->inf->done) {
158 ret = ethosu_firmware_reset(cancellation->edev);
159 if (ret)
Davide Grohmann32660f92022-04-27 16:49:07 +0200160 goto deregister;
Davide Grohmann8b1fe552022-04-07 16:58:32 +0200161 }
162
Davide Grohmann32660f92022-04-27 16:49:07 +0200163deregister:
164 ethosu_mailbox_deregister(&cancellation->edev->mailbox,
165 &cancellation->msg);
166
167kfree:
168 dev_info(cancellation->edev->dev,
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200169 "Cancel inference destroy. cancel=0x%pK\n", cancellation);
Davide Grohmann32660f92022-04-27 16:49:07 +0200170 /* decrease the reference on the inference we are refering to */
171 ethosu_inference_put(cancellation->inf);
172 devm_kfree(cancellation->edev->dev, cancellation);
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100173
174 return ret;
175}
176
177void ethosu_cancel_inference_rsp(struct ethosu_device *edev,
178 struct ethosu_core_cancel_inference_rsp *rsp)
179{
Davide Grohmann32660f92022-04-27 16:49:07 +0200180 int id = (int)rsp->user_arg;
181 struct ethosu_mailbox_msg *msg;
182 struct ethosu_cancel_inference *cancellation;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100183
Davide Grohmann32660f92022-04-27 16:49:07 +0200184 msg = ethosu_mailbox_find(&edev->mailbox, id);
185 if (IS_ERR(msg)) {
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100186 dev_warn(edev->dev,
187 "Handle not found in cancel inference list. handle=0x%p\n",
188 rsp);
189
190 return;
191 }
192
Davide Grohmann32660f92022-04-27 16:49:07 +0200193 cancellation = container_of(msg, typeof(*cancellation), msg);
194
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100195 if (completion_done(&cancellation->done))
196 return;
197
198 cancellation->errno = 0;
199 switch (rsp->status) {
200 case ETHOSU_CORE_STATUS_OK:
201 cancellation->uapi->status = ETHOSU_UAPI_STATUS_OK;
202 break;
203 case ETHOSU_CORE_STATUS_ERROR:
204 cancellation->uapi->status = ETHOSU_UAPI_STATUS_ERROR;
205 break;
206 }
207
208 complete(&cancellation->done);
209}