Add support for inference cancellation

Send cancel inference messages to the ethosu subsystem to abort
inference execution there.  Also mark inference as aborted in the
linux driver stack itself, so pending inference messages are not
resent when resetting the firmware.

Change-Id: I244c2b119fd7995d14e3859815abf2a00c7f0583
diff --git a/kernel/ethosu_inference.c b/kernel/ethosu_inference.c
index 73a8c06..0599b53 100644
--- a/kernel/ethosu_inference.c
+++ b/kernel/ethosu_inference.c
@@ -28,6 +28,7 @@
 #include "ethosu_core_interface.h"
 #include "ethosu_device.h"
 #include "ethosu_network.h"
+#include "ethosu_cancel_inference.h"
 
 #include <linux/anon_inodes.h>
 #include <linux/file.h>
@@ -76,6 +77,12 @@
 	case ETHOSU_UAPI_STATUS_REJECTED: {
 		return "Rejected";
 	}
+	case ETHOSU_UAPI_STATUS_ABORTED: {
+		return "Aborted";
+	}
+	case ETHOSU_UAPI_STATUS_ABORTING: {
+		return "Aborting";
+	}
 	default: {
 		return "Unknown";
 	}
@@ -112,15 +119,19 @@
 		container_of(msg, typeof(*inf), msg);
 	int ret;
 
-	/* Decrement reference count if inference was pending reponse */
-	if (!inf->done) {
-		ret = ethosu_inference_put(inf);
-		if (ret)
-			return;
-	}
+	if (inf->done)
+		return;
 
-	/* Fail inference and wake up any waiting process */
-	inf->status = ETHOSU_UAPI_STATUS_ERROR;
+	/* Decrement reference count if inference was pending reponse */
+	ret = ethosu_inference_put(inf);
+	if (ret)
+		return;
+
+	/* Set status accordingly to the inference state */
+	inf->status = inf->status == ETHOSU_UAPI_STATUS_ABORTING ?
+		      ETHOSU_UAPI_STATUS_ABORTED :
+		      ETHOSU_UAPI_STATUS_ERROR;
+	/* Mark it done and wake up the waiting process */
 	inf->done = true;
 	wake_up_interruptible(&inf->waitq);
 }
@@ -135,6 +146,13 @@
 	if (inf->done)
 		return 0;
 
+	/* If marked as ABORTING simply fail it and return */
+	if (inf->status == ETHOSU_UAPI_STATUS_ABORTING) {
+		ethosu_inference_fail(msg);
+
+		return 0;
+	}
+
 	/* Decrement reference count for pending request */
 	ret = ethosu_inference_put(inf);
 	if (ret)
@@ -241,8 +259,22 @@
 
 		break;
 	}
+	case ETHOSU_IOCTL_INFERENCE_CANCEL: {
+		struct ethosu_uapi_cancel_inference_status uapi;
+
+		dev_info(inf->edev->dev, "Ioctl: Cancel Inference. Handle=%p\n",
+			 inf);
+
+		ret = ethosu_cancel_inference_request(inf, &uapi);
+		if (ret)
+			break;
+
+		ret = copy_to_user(udata, &uapi, sizeof(uapi)) ? -EFAULT : 0;
+
+		break;
+	}
 	default: {
-		dev_err(inf->edev->dev, "Invalid ioctl. cmd=%u, arg=%lu",
+		dev_err(inf->edev->dev, "Invalid ioctl. cmd=%u, arg=%lu\n",
 			cmd, arg);
 		break;
 	}
@@ -422,6 +454,8 @@
 		}
 	} else if (rsp->status == ETHOSU_CORE_STATUS_REJECTED) {
 		inf->status = ETHOSU_UAPI_STATUS_REJECTED;
+	} else if (rsp->status == ETHOSU_CORE_STATUS_ABORTED) {
+		inf->status = ETHOSU_UAPI_STATUS_ABORTED;
 	} else {
 		inf->status = ETHOSU_UAPI_STATUS_ERROR;
 	}
@@ -450,6 +484,5 @@
 
 	inf->done = true;
 	wake_up_interruptible(&inf->waitq);
-
 	ethosu_inference_put(inf);
 }