qseecom: check if listener is not ready to receive request

TA may send listener request when listener service is still
not ready to receive request, especially during power on/off
cycle. To prevent device stuck in this situation, qseecom
should return error response to TA if listener is not ready
to receive request.

Change-Id: I121a77ec5b7ade4011ce982fac9127e3018de649
Signed-off-by: Zhen Kong <zkong@codeaurora.org>
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index a8ffda2..ea5396f 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1639,6 +1639,23 @@
 	}
 }
 
+/* wake up listener receive request wq retry delay (ms) and max attemp count */
+#define QSEECOM_WAKE_LISTENER_RCVWQ_DELAY          10
+#define QSEECOM_WAKE_LISTENER_RCVWQ_MAX_ATTEMP     3
+
+static int __qseecom_retry_wake_up_listener_rcv_wq(
+			struct qseecom_registered_listener_list *ptr_svc)
+{
+	int retry = 0;
+
+	while (ptr_svc->rcv_req_flag == 1 &&
+		retry++ < QSEECOM_WAKE_LISTENER_RCVWQ_MAX_ATTEMP) {
+		wake_up_interruptible(&ptr_svc->rcv_req_wq);
+		msleep(QSEECOM_WAKE_LISTENER_RCVWQ_DELAY);
+	}
+	return ptr_svc->rcv_req_flag == 1;
+}
+
 static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
 					struct qseecom_command_scm_resp *resp)
 {
@@ -1706,6 +1723,15 @@
 			status = QSEOS_RESULT_FAILURE;
 			goto err_resp;
 		}
+
+		if (ptr_svc->rcv_req_flag == 1 &&
+			__qseecom_retry_wake_up_listener_rcv_wq(ptr_svc)) {
+			pr_err("Service %d is not ready to receive request\n",
+					lstnr);
+			rc = -ENOENT;
+			status = QSEOS_RESULT_FAILURE;
+			goto err_resp;
+		}
 		pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n");
 
 		/* initialize the new signal mask with all signals*/
@@ -2017,6 +2043,15 @@
 			status = QSEOS_RESULT_FAILURE;
 			goto err_resp;
 		}
+
+		if (ptr_svc->rcv_req_flag == 1 &&
+			__qseecom_retry_wake_up_listener_rcv_wq(ptr_svc)) {
+			pr_err("Service %d is not ready to receive request\n",
+					lstnr);
+			rc = -ENOENT;
+			status = QSEOS_RESULT_FAILURE;
+			goto err_resp;
+		}
 		pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n");
 
 		/* initialize the new signal mask with all signals*/
@@ -3843,7 +3878,7 @@
 		if (wait_event_freezable(this_lstnr->rcv_req_wq,
 				__qseecom_listener_has_rcvd_req(data,
 				this_lstnr))) {
-			pr_debug("Interrupted: exiting Listener Service = %d\n",
+			pr_warn("Interrupted: exiting Listener Service = %d\n",
 						(uint32_t)data->listener.id);
 			/* woken up for different reason */
 			return -ERESTARTSYS;
@@ -7687,6 +7722,7 @@
 			data->type, data->mode, data);
 		switch (data->type) {
 		case QSEECOM_LISTENER_SERVICE:
+			pr_warn("release lsnr svc %d\n", data->listener.id);
 			__qseecom_listener_abort_all(1);
 			mutex_lock(&app_access_lock);
 			ret = qseecom_unregister_listener(data);