Add support for rejected inference responses

Change-Id: I62e13df69c712ed4cf70766429b4cb13fc9c9dcb
diff --git a/driver_library/include/ethosu.hpp b/driver_library/include/ethosu.hpp
index a12d668..61e2bc5 100644
--- a/driver_library/include/ethosu.hpp
+++ b/driver_library/include/ethosu.hpp
@@ -180,6 +180,15 @@
     std::vector<size_t> ofmDims;
 };
 
+enum class InferenceStatus {
+    OK,
+    ERROR,
+    RUNNING,
+    REJECTED,
+};
+
+std::ostream &operator<<(std::ostream &out, const InferenceStatus &v);
+
 class Inference {
 public:
     template <typename T>
@@ -220,7 +229,7 @@
     int wait(int64_t timeoutNanos = -1) const;
     const std::vector<uint32_t> getPmuCounters() const;
     uint64_t getCycleCounter() const;
-    bool failed() const;
+    InferenceStatus status() const;
     int getFd() const;
     const std::shared_ptr<Network> getNetwork() const;
     std::vector<std::shared_ptr<Buffer>> &getIfmBuffers();
diff --git a/driver_library/src/ethosu.cpp b/driver_library/src/ethosu.cpp
index 2b1da45..0da30c3 100644
--- a/driver_library/src/ethosu.cpp
+++ b/driver_library/src/ethosu.cpp
@@ -330,6 +330,20 @@
  * Inference
  ****************************************************************************/
 
+ostream &operator<<(ostream &out, const InferenceStatus &status) {
+    switch (status) {
+    case InferenceStatus::OK:
+        return out << "ok";
+    case InferenceStatus::ERROR:
+        return out << "error";
+    case InferenceStatus::RUNNING:
+        return out << "running";
+    case InferenceStatus::REJECTED:
+        return out << "rejected";
+    }
+    throw Exception("Unknown inference status");
+}
+
 Inference::~Inference() noexcept(false) {
     eclose(fd);
 }
@@ -395,12 +409,23 @@
     return eppoll(&pfd, 1, &tmo_p, NULL);
 }
 
-bool Inference::failed() const {
+InferenceStatus Inference::status() const {
     ethosu_uapi_result_status uapi;
 
     eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
 
-    return uapi.status != ETHOSU_UAPI_STATUS_OK;
+    switch (uapi.status) {
+    case ETHOSU_UAPI_STATUS_OK:
+        return InferenceStatus::OK;
+    case ETHOSU_UAPI_STATUS_ERROR:
+        return InferenceStatus::ERROR;
+    case ETHOSU_UAPI_STATUS_RUNNING:
+        return InferenceStatus::RUNNING;
+    case ETHOSU_UAPI_STATUS_REJECTED:
+        return InferenceStatus::REJECTED;
+    }
+
+    throw Exception("Unknown inference status");
 }
 
 const std::vector<uint32_t> Inference::getPmuCounters() const {
diff --git a/kernel/ethosu_core_interface.h b/kernel/ethosu_core_interface.h
index 5a6e55d..76fe35e 100644
--- a/kernel/ethosu_core_interface.h
+++ b/kernel/ethosu_core_interface.h
@@ -95,7 +95,9 @@
  */
 enum ethosu_core_status {
 	ETHOSU_CORE_STATUS_OK,
-	ETHOSU_CORE_STATUS_ERROR
+	ETHOSU_CORE_STATUS_ERROR,
+	ETHOSU_CORE_STATUS_RUNNING,
+	ETHOSU_CORE_STATUS_REJECTED,
 };
 
 /**
diff --git a/kernel/ethosu_inference.c b/kernel/ethosu_inference.c
index 3c18bbd..73a8c06 100644
--- a/kernel/ethosu_inference.c
+++ b/kernel/ethosu_inference.c
@@ -70,6 +70,12 @@
 	case ETHOSU_UAPI_STATUS_ERROR: {
 		return "Error";
 	}
+	case ETHOSU_UAPI_STATUS_RUNNING: {
+		return "Running";
+	}
+	case ETHOSU_UAPI_STATUS_REJECTED: {
+		return "Rejected";
+	}
 	default: {
 		return "Unknown";
 	}
@@ -93,6 +99,8 @@
 	if (ret)
 		return ret;
 
+	inf->status = ETHOSU_UAPI_STATUS_RUNNING;
+
 	ethosu_inference_get(inf);
 
 	return 0;
@@ -412,30 +420,34 @@
 			if (ret)
 				inf->status = ETHOSU_UAPI_STATUS_ERROR;
 		}
+	} else if (rsp->status == ETHOSU_CORE_STATUS_REJECTED) {
+		inf->status = ETHOSU_UAPI_STATUS_REJECTED;
 	} else {
 		inf->status = ETHOSU_UAPI_STATUS_ERROR;
 	}
 
-	for (i = 0; i < ETHOSU_CORE_PMU_MAX; i++) {
-		inf->pmu_event_config[i] = rsp->pmu_event_config[i];
-		inf->pmu_event_count[i] = rsp->pmu_event_count[i];
+	if (inf->status == ETHOSU_UAPI_STATUS_OK) {
+		for (i = 0; i < ETHOSU_CORE_PMU_MAX; i++) {
+			inf->pmu_event_config[i] = rsp->pmu_event_config[i];
+			inf->pmu_event_count[i] = rsp->pmu_event_count[i];
+		}
+
+		inf->pmu_cycle_counter_enable = rsp->pmu_cycle_counter_enable;
+		inf->pmu_cycle_counter_count = rsp->pmu_cycle_counter_count;
+
+		dev_info(edev->dev,
+			 "PMU events. config=[%u, %u, %u, %u], count=[%u, %u, %u, %u]\n",
+			 inf->pmu_event_config[0], inf->pmu_event_config[1],
+			 inf->pmu_event_config[2], inf->pmu_event_config[3],
+			 inf->pmu_event_count[0], inf->pmu_event_count[1],
+			 inf->pmu_event_count[2], inf->pmu_event_count[3]);
+
+		dev_info(edev->dev,
+			 "PMU cycle counter. enable=%u, count=%llu\n",
+			 inf->pmu_cycle_counter_enable,
+			 inf->pmu_cycle_counter_count);
 	}
 
-	inf->pmu_cycle_counter_enable = rsp->pmu_cycle_counter_enable;
-	inf->pmu_cycle_counter_count = rsp->pmu_cycle_counter_count;
-
-	dev_info(edev->dev,
-		 "PMU events. config=[%u, %u, %u, %u], count=[%u, %u, %u, %u]\n",
-		 inf->pmu_event_config[0], inf->pmu_event_config[1],
-		 inf->pmu_event_config[2], inf->pmu_event_config[3],
-		 inf->pmu_event_count[0], inf->pmu_event_count[1],
-		 inf->pmu_event_count[2], inf->pmu_event_count[3]);
-
-	dev_info(edev->dev,
-		 "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);
 
diff --git a/kernel/uapi/ethosu.h b/kernel/uapi/ethosu.h
index fda7fc2..4627cb9 100644
--- a/kernel/uapi/ethosu.h
+++ b/kernel/uapi/ethosu.h
@@ -75,7 +75,9 @@
  */
 enum ethosu_uapi_status {
 	ETHOSU_UAPI_STATUS_OK,
-	ETHOSU_UAPI_STATUS_ERROR
+	ETHOSU_UAPI_STATUS_ERROR,
+	ETHOSU_UAPI_STATUS_RUNNING,
+	ETHOSU_UAPI_STATUS_REJECTED,
 };
 
 /**
diff --git a/utils/inference_runner/inference_runner.cpp b/utils/inference_runner/inference_runner.cpp
index b6a5cdb..21e133c 100644
--- a/utils/inference_runner/inference_runner.cpp
+++ b/utils/inference_runner/inference_runner.cpp
@@ -254,17 +254,18 @@
 
         int ofmIndex = 0;
         for (auto &inference : inferences) {
+            cout << "Inference status: " << inference->status() << endl;
 
             /* make sure the wait completes ok */
             try {
+                cout << "Wait for inference" << endl;
                 inference->wait(timeout);
             } catch (std::exception &e) {
                 cout << "Failed to wait for inference completion: " << e.what() << endl;
                 exit(1);
             }
 
-            string status = inference->failed() ? "failed" : "success";
-            cout << "Inference status: " << status << endl;
+            cout << "Inference status: " << inference->status() << endl;
 
             string ofmFilename = ofmArg + "." + to_string(ofmIndex);
             ofstream ofmStream(ofmFilename, ios::binary);
@@ -273,7 +274,7 @@
                 exit(1);
             }
 
-            if (!inference->failed()) {
+            if (inference->status() == InferenceStatus::OK) {
                 /* The inference completed and has ok status */
                 for (auto &ofmBuffer : inference->getOfmBuffers()) {
                     cout << "OFM size: " << ofmBuffer->size() << endl;