aboutsummaryrefslogtreecommitdiff
path: root/kernel/ethosu_inference.c
diff options
context:
space:
mode:
authorKristofer Jonsson <kristofer.jonsson@arm.com>2022-03-17 17:15:52 +0100
committerKristofer Jonsson <kristofer.jonsson@arm.com>2022-04-04 15:34:47 +0200
commit442fefb74a28307cfcd009723504ea5ac1353430 (patch)
treee22c128b2888de206d84c48f19e4d268f782d10e /kernel/ethosu_inference.c
parentf5b98c965c51def4f63d7fb198f70180e195b2e8 (diff)
downloadethos-u-linux-driver-stack-442fefb74a28307cfcd009723504ea5ac1353430.tar.gz
Reset firmware
Reset the firmware if it becomes unresponsive. Use ping to send keep alive requests. Only monitor ping and inference request messages. The other messages pass no resources to the firmware and can be cancelled without resetting the firmware. Change-Id: Ifbcc370f02d79a64f25598f11376a1dc84a7a066
Diffstat (limited to 'kernel/ethosu_inference.c')
-rw-r--r--kernel/ethosu_inference.c71
1 files changed, 48 insertions, 23 deletions
diff --git a/kernel/ethosu_inference.c b/kernel/ethosu_inference.c
index ad31f06..3c18bbd 100644
--- a/kernel/ethosu_inference.c
+++ b/kernel/ethosu_inference.c
@@ -28,7 +28,6 @@
#include "ethosu_core_interface.h"
#include "ethosu_device.h"
#include "ethosu_network.h"
-#include "uapi/ethosu.h"
#include <linux/anon_inodes.h>
#include <linux/file.h>
@@ -81,9 +80,6 @@ static int ethosu_inference_send(struct ethosu_inference *inf)
{
int ret;
- if (inf->pending)
- return -EINVAL;
-
inf->status = ETHOSU_UAPI_STATUS_ERROR;
ret = ethosu_mailbox_inference(&inf->edev->mailbox, inf,
@@ -97,24 +93,51 @@ static int ethosu_inference_send(struct ethosu_inference *inf)
if (ret)
return ret;
- inf->pending = true;
-
ethosu_inference_get(inf);
return 0;
}
-static int ethosu_inference_find(struct ethosu_inference *inf,
- struct list_head *inference_list)
+static void ethosu_inference_fail(struct ethosu_mailbox_msg *msg)
{
- struct ethosu_inference *cur;
+ struct ethosu_inference *inf =
+ container_of(msg, typeof(*inf), msg);
+ int ret;
- list_for_each_entry(cur, inference_list, list) {
- if (cur == inf)
- return 0;
+ /* Decrement reference count if inference was pending reponse */
+ if (!inf->done) {
+ ret = ethosu_inference_put(inf);
+ if (ret)
+ return;
}
- return -EINVAL;
+ /* Fail inference and wake up any waiting process */
+ inf->status = ETHOSU_UAPI_STATUS_ERROR;
+ inf->done = true;
+ wake_up_interruptible(&inf->waitq);
+}
+
+static int ethosu_inference_resend(struct ethosu_mailbox_msg *msg)
+{
+ struct ethosu_inference *inf =
+ container_of(msg, typeof(*inf), msg);
+ int ret;
+
+ /* Don't resend request if response has already been received */
+ if (inf->done)
+ return 0;
+
+ /* Decrement reference count for pending request */
+ ret = ethosu_inference_put(inf);
+ if (ret)
+ return 0;
+
+ /* Resend request */
+ ret = ethosu_inference_send(inf);
+ if (ret)
+ return ret;
+
+ return 0;
}
static bool ethosu_inference_verify(struct file *file)
@@ -131,7 +154,7 @@ static void ethosu_inference_kref_destroy(struct kref *kref)
"Inference destroy. handle=0x%pK, status=%d\n",
inf, inf->status);
- list_del(&inf->list);
+ list_del(&inf->msg.list);
while (inf->ifm_count-- > 0)
ethosu_buffer_put(inf->ifm[inf->ifm_count]);
@@ -165,7 +188,7 @@ static unsigned int ethosu_inference_poll(struct file *file,
poll_wait(file, &inf->waitq, wait);
- if (!inf->pending)
+ if (inf->done)
ret |= POLLIN;
return ret;
@@ -237,10 +260,12 @@ int ethosu_inference_create(struct ethosu_device *edev,
inf->edev = edev;
inf->net = net;
- inf->pending = false;
+ inf->done = false;
inf->status = ETHOSU_UAPI_STATUS_ERROR;
kref_init(&inf->kref);
init_waitqueue_head(&inf->waitq);
+ inf->msg.fail = ethosu_inference_fail;
+ inf->msg.resend = ethosu_inference_resend;
/* Get pointer to IFM buffers */
for (i = 0; i < uapi->ifm_count; i++) {
@@ -296,8 +321,8 @@ int ethosu_inference_create(struct ethosu_device *edev,
inf->file = fget(ret);
fput(inf->file);
- /* Add inference to inference list */
- list_add(&inf->list, &edev->inference_list);
+ /* Add inference to pending list */
+ list_add(&inf->msg.list, &edev->mailbox.pending_list);
/* Send inference request to Arm Ethos-U subsystem */
(void)ethosu_inference_send(inf);
@@ -350,9 +375,9 @@ void ethosu_inference_get(struct ethosu_inference *inf)
kref_get(&inf->kref);
}
-void ethosu_inference_put(struct ethosu_inference *inf)
+int ethosu_inference_put(struct ethosu_inference *inf)
{
- kref_put(&inf->kref, &ethosu_inference_kref_destroy);
+ return kref_put(&inf->kref, &ethosu_inference_kref_destroy);
}
void ethosu_inference_rsp(struct ethosu_device *edev,
@@ -363,7 +388,7 @@ void ethosu_inference_rsp(struct ethosu_device *edev,
int ret;
int i;
- ret = ethosu_inference_find(inf, &edev->inference_list);
+ ret = ethosu_mailbox_find(&edev->mailbox, &inf->msg);
if (ret) {
dev_warn(edev->dev,
"Handle not found in inference list. handle=0x%p\n",
@@ -372,8 +397,6 @@ void ethosu_inference_rsp(struct ethosu_device *edev,
return;
}
- inf->pending = false;
-
if (rsp->status == ETHOSU_CORE_STATUS_OK &&
inf->ofm_count <= ETHOSU_CORE_BUFFER_MAX) {
uint32_t i;
@@ -412,6 +435,8 @@ void ethosu_inference_rsp(struct ethosu_device *edev,
"PMU cycle counter. enable=%u, count=%llu\n",
inf->pmu_cycle_counter_enable,
inf->pmu_cycle_counter_count);
+
+ inf->done = true;
wake_up_interruptible(&inf->waitq);
ethosu_inference_put(inf);