From 7d97944f8d594377807f378d7d2c7b9d5199c0f5 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Thu, 13 May 2021 16:48:41 +0530 Subject: [PATCH] rpmsg: glink: wait for intent request completion Wait for actul intent allocation to complete before again requesting for same intent. Currently on getting intent request ack glink looks for allocated intent and if it is not found it again requests. In some cases remote host may delay allocation of intents but acknowledge it immediately, in such cases glink will keep on requesting same intent repeatedly. Now added code to wait for actual intent allocation to complete and timeout if it is not allocated within 10 sec. Change-Id: I346eb207422450cbeedc94e6451c6491bbf58bf0 Signed-off-by: Deepak Kumar Singh --- drivers/rpmsg/qcom_glink_native.c | 62 +++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 54b9ced25052..bde45ef02660 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -196,8 +196,10 @@ enum { * @open_req: completed once open-request has been received * @intent_req_lock: Synchronises multiple intent requests * @intent_req_result: Result of intent request - * @intent_req_comp: Status of intent request completion - * @intent_req_event: Waitqueue for @intent_req_comp + * @intent_req_acked: Status of intent request acknowledgment + * @intent_req_completed: Status of intent request completion + * @intent_req_ack: Waitqueue for @intent_req_acked + * @intent_req_comp: Waitqueue for @intent_req_completed * @lsigs: local side signals * @rsigs: remote side signals */ @@ -231,8 +233,10 @@ struct glink_channel { struct mutex intent_req_lock; bool intent_req_result; bool channel_ready; - atomic_t intent_req_comp; - wait_queue_head_t intent_req_event; + atomic_t intent_req_acked; + atomic_t intent_req_completed; + wait_queue_head_t intent_req_ack; + wait_queue_head_t intent_req_comp; unsigned int lsigs; unsigned int rsigs; @@ -286,8 +290,10 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink, init_completion(&channel->open_req); init_completion(&channel->open_ack); - atomic_set(&channel->intent_req_comp, 0); - init_waitqueue_head(&channel->intent_req_event); + atomic_set(&channel->intent_req_acked, 0); + atomic_set(&channel->intent_req_completed, 0); + init_waitqueue_head(&channel->intent_req_ack); + init_waitqueue_head(&channel->intent_req_comp); INIT_LIST_HEAD(&channel->done_intents); kthread_init_work(&channel->intent_work, qcom_glink_rx_done_work); @@ -310,8 +316,10 @@ static void qcom_glink_channel_release(struct kref *ref) CH_INFO(channel, "\n"); channel->intent_req_result = false; - atomic_inc(&channel->intent_req_comp); - wake_up(&channel->intent_req_event); + atomic_inc(&channel->intent_req_acked); + wake_up(&channel->intent_req_ack); + atomic_inc(&channel->intent_req_completed); + wake_up(&channel->intent_req_comp); /* cancel pending rx_done work */ kthread_cancel_work_sync(&channel->intent_work); @@ -502,8 +510,8 @@ static void qcom_glink_handle_intent_req_ack(struct qcom_glink *glink, } channel->intent_req_result = granted; - atomic_inc(&channel->intent_req_comp); - wake_up(&channel->intent_req_event); + atomic_inc(&channel->intent_req_acked); + wake_up(&channel->intent_req_ack); CH_INFO(channel, "\n"); } @@ -1142,6 +1150,9 @@ static void qcom_glink_handle_intent(struct qcom_glink *glink, dev_err(glink->dev, "failed to store remote intent\n"); } + atomic_inc(&channel->intent_req_completed); + wake_up(&channel->intent_req_comp); + kfree(msg); qcom_glink_rx_advance(glink, ALIGN(msglen, 8)); } @@ -1532,7 +1543,8 @@ static int qcom_glink_request_intent(struct qcom_glink *glink, mutex_lock(&channel->intent_req_lock); - atomic_set(&channel->intent_req_comp, 0); + atomic_set(&channel->intent_req_acked, 0); + atomic_set(&channel->intent_req_completed, 0); cmd.id = RPM_CMD_RX_INTENT_REQ; cmd.cid = channel->lcid; @@ -1544,11 +1556,11 @@ static int qcom_glink_request_intent(struct qcom_glink *glink, if (ret) goto unlock; - ret = wait_event_timeout(channel->intent_req_event, - atomic_read(&channel->intent_req_comp) || + ret = wait_event_timeout(channel->intent_req_ack, + atomic_read(&channel->intent_req_acked) || atomic_read(&glink->in_reset), 10 * HZ); if (!ret) { - dev_err(glink->dev, "intent request timed out\n"); + dev_err(glink->dev, "intent request ack timed out\n"); ret = -ETIMEDOUT; } else if (atomic_read(&glink->in_reset)) { CH_INFO(channel, "ssr detected\n"); @@ -1609,6 +1621,25 @@ static int __qcom_glink_send(struct glink_channel *channel, ret = qcom_glink_request_intent(glink, channel, len); if (ret < 0) return ret; + + /*Wait for intents to arrive*/ + ret = wait_event_timeout(channel->intent_req_comp, + atomic_read(&channel->intent_req_completed) || + atomic_read(&glink->in_reset), 10 * HZ); + + if (!ret) { + dev_err(glink->dev, + "intent request completion timed out\n"); + ret = -ETIMEDOUT; + } else if (atomic_read(&glink->in_reset)) { + CH_INFO(channel, "ssr detected\n"); + ret = -ECONNRESET; + } else { + ret = channel->intent_req_result ? 0 : -ECANCELED; + } + + if (ret < 0) + return ret; } iid = intent->id; @@ -2036,7 +2067,8 @@ static void qcom_glink_notif_reset(void *data) spin_lock_irqsave(&glink->idr_lock, flags); idr_for_each_entry(&glink->lcids, channel, cid) { - wake_up(&channel->intent_req_event); + wake_up(&channel->intent_req_ack); + wake_up(&channel->intent_req_comp); } spin_unlock_irqrestore(&glink->idr_lock, flags); }