Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7d97944f authored by Deepak Kumar Singh's avatar Deepak Kumar Singh
Browse files

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: default avatarDeepak Kumar Singh <deesin@codeaurora.org>
parent 0611102d
Loading
Loading
Loading
Loading
+47 −15
Original line number Diff line number Diff line
@@ -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);
}