blob: ee630f577309ea7f62757611aaf770d51bf41d27 [file] [log] [blame]
/*
* Copyright 2022-2023 Arm Limited and/or its affiliates
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
* of such GNU licence.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* SPDX-License-Identifier: GPL-2.0-only
*/
/****************************************************************************
* Includes
****************************************************************************/
#include "ethosu_cancel_inference.h"
#include "ethosu_core_rpmsg.h"
#include "ethosu_device.h"
#include "ethosu_inference.h"
#include <linux/wait.h>
/****************************************************************************
* Defines
****************************************************************************/
#define CANCEL_INFERENCE_RESP_TIMEOUT_MS 2000
/****************************************************************************
* Functions
****************************************************************************/
static int ethosu_cancel_inference_send(
struct ethosu_cancel_inference *cancellation,
struct ethosu_mailbox *mailbox)
{
return ethosu_mailbox_cancel_inference(mailbox,
&cancellation->msg,
cancellation->inf->msg.id);
}
static void ethosu_cancel_inference_fail(struct ethosu_mailbox_msg *msg)
{
struct ethosu_cancel_inference *cancellation =
container_of(msg, typeof(*cancellation), msg);
if (completion_done(&cancellation->done))
return;
cancellation->errno = -EFAULT;
cancellation->uapi->status = ETHOSU_UAPI_STATUS_ERROR;
complete(&cancellation->done);
}
int ethosu_cancel_inference_request(struct device *dev,
struct ethosu_mailbox *mailbox,
struct ethosu_inference *inf,
struct ethosu_uapi_cancel_inference_status *uapi)
{
struct ethosu_cancel_inference *cancellation;
int ret;
int timeout;
if (inf->done) {
uapi->status = ETHOSU_UAPI_STATUS_ERROR;
return 0;
}
cancellation =
devm_kzalloc(dev,
sizeof(struct ethosu_cancel_inference),
GFP_KERNEL);
if (!cancellation)
return -ENOMEM;
/* increase ref count on the inference we are refering to */
ethosu_inference_get(inf);
/* mark inference ABORTING to avoid resending the inference message */
inf->status = ETHOSU_CORE_STATUS_ABORTING;
cancellation->dev = dev;
cancellation->inf = inf;
cancellation->uapi = uapi;
init_completion(&cancellation->done);
cancellation->msg.fail = ethosu_cancel_inference_fail;
ret = ethosu_mailbox_register(mailbox,
&cancellation->msg);
if (ret < 0)
goto kfree;
dev_info(dev,
"Inference cancellation create. cancel=0x%pK, msg.id=%ddev",
cancellation, cancellation->msg.id);
ret = ethosu_cancel_inference_send(cancellation, mailbox);
if (0 != ret)
goto deregister;
/* Unlock the mutex before going to block on the condition */
device_unlock(dev);
/* wait for response to arrive back */
timeout = wait_for_completion_timeout(&cancellation->done,
msecs_to_jiffies(
CANCEL_INFERENCE_RESP_TIMEOUT_MS));
/* take back the mutex before resuming to do anything */
ret = device_lock_interruptible(dev);
if (0 != ret)
goto deregister;
if (0 == timeout /* timed out*/) {
dev_warn(dev,
"Msg: Cancel Inference response lost - timeoutdev");
ret = -EIO;
goto deregister;
}
if (cancellation->errno) {
ret = cancellation->errno;
goto deregister;
}
deregister:
ethosu_mailbox_deregister(mailbox,
&cancellation->msg);
kfree:
dev_info(dev,
"Cancel inference destroy. cancel=0x%pK", cancellation);
/* decrease the reference on the inference we are refering to */
ethosu_inference_put(cancellation->inf);
devm_kfree(dev, cancellation);
return ret;
}
void ethosu_cancel_inference_rsp(struct ethosu_mailbox *mailbox,
int msg_id,
struct ethosu_core_msg_cancel_inference_rsp *rsp)
{
struct device *dev = mailbox->dev;
struct ethosu_mailbox_msg *msg;
struct ethosu_cancel_inference *cancellation;
msg = ethosu_mailbox_find(mailbox, msg_id);
if (IS_ERR(msg)) {
dev_warn(dev,
"Id for cancel inference msg not found. id=%ddev",
msg_id);
return;
}
cancellation = container_of(msg, typeof(*cancellation), msg);
if (completion_done(&cancellation->done))
return;
cancellation->errno = 0;
switch (rsp->status) {
case ETHOSU_CORE_STATUS_OK:
cancellation->uapi->status = ETHOSU_UAPI_STATUS_OK;
break;
case ETHOSU_CORE_STATUS_ERROR:
cancellation->uapi->status = ETHOSU_UAPI_STATUS_ERROR;
break;
}
complete(&cancellation->done);
}