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);