aboutsummaryrefslogtreecommitdiff
path: root/kernel/rpmsg/ethosu_rpmsg_cancel_inference.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/rpmsg/ethosu_rpmsg_cancel_inference.c')
-rw-r--r--kernel/rpmsg/ethosu_rpmsg_cancel_inference.c191
1 files changed, 191 insertions, 0 deletions
diff --git a/kernel/rpmsg/ethosu_rpmsg_cancel_inference.c b/kernel/rpmsg/ethosu_rpmsg_cancel_inference.c
new file mode 100644
index 0000000..5d46434
--- /dev/null
+++ b/kernel/rpmsg/ethosu_rpmsg_cancel_inference.c
@@ -0,0 +1,191 @@
+/*
+ * SPDX-FileCopyrightText: Copyright 2022-2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * 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.
+ *
+ */
+
+/****************************************************************************
+ * Includes
+ ****************************************************************************/
+
+#include <rpmsg/ethosu_rpmsg_cancel_inference.h>
+
+#include <common/ethosu_device.h>
+#include <rpmsg/ethosu_rpmsg.h>
+#include <rpmsg/ethosu_rpmsg_inference.h>
+
+#include <linux/remoteproc.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_UAPI_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_dbg(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;
+
+ rproc_report_crash(rproc_get_by_child(dev), RPROC_FATAL_ERROR);
+ goto deregister;
+ }
+
+ if (cancellation->errno) {
+ ret = cancellation->errno;
+ rproc_report_crash(rproc_get_by_child(dev), RPROC_FATAL_ERROR);
+ goto deregister;
+ }
+
+ if (inf->status != ETHOSU_UAPI_STATUS_ABORTED)
+ inf->status = ETHOSU_UAPI_STATUS_ABORTED;
+
+deregister:
+ ethosu_mailbox_deregister(mailbox,
+ &cancellation->msg);
+
+kfree:
+ dev_dbg(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,
+ ETHOSU_CORE_MSG_CANCEL_INFERENCE_REQ);
+ if (IS_ERR(msg)) {
+ dev_warn(dev,
+ "Id for cancel inference msg not found. Id=0x%x: %ld",
+ msg_id, PTR_ERR(msg));
+
+ 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);
+}