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

Commit 17a12f2a authored by Arun Kumar Neelakantam's avatar Arun Kumar Neelakantam Committed by Gerrit - the friendly Code Review server
Browse files

rpmsg: glink: Send READ_NOTIFY command in FIFO full case



The current design sleeps unconditionally in TX FIFO full case and
wakeup only after sleep timer expires which adds random delays in
clients TX path.

Avoid sleep and use READ_NOTIFY command so that writer can be woken up
when remote notifies about read completion by sending IRQ.

Change-Id: I1b44df0ec437d4e76aff181470fcf4cafbdd098a
Signed-off-by: default avatarArun Kumar Neelakantam <aneela@codeaurora.org>
parent 84b56d3a
Loading
Loading
Loading
Loading
+43 −5
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0
/*
/*
 * Copyright (c) 2016-2017, Linaro Ltd
 * Copyright (c) 2016-2017, Linaro Ltd
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
 */
 */


#include <linux/idr.h>
#include <linux/idr.h>
@@ -121,6 +121,8 @@ struct glink_core_rx_intent {
 * @in_reset:	reset status of this edge
 * @in_reset:	reset status of this edge
 * @features:	remote features
 * @features:	remote features
 * @intentless:	flag to indicate that there is no intent
 * @intentless:	flag to indicate that there is no intent
 * @tx_avail_notify: Waitqueue for pending tx tasks
 * @sent_read_notify: flag to check cmd sent or not
 * @ilc:	ipc logging context reference
 * @ilc:	ipc logging context reference
 */
 */
struct qcom_glink {
struct qcom_glink {
@@ -154,6 +156,9 @@ struct qcom_glink {


	bool intentless;
	bool intentless;


	wait_queue_head_t tx_avail_notify;
	bool sent_read_notify;

	void *ilc;
	void *ilc;
};
};


@@ -357,6 +362,22 @@ static void qcom_glink_pipe_reset(struct qcom_glink *glink)
		glink->rx_pipe->reset(glink->rx_pipe);
		glink->rx_pipe->reset(glink->rx_pipe);
}
}


static void qcom_glink_send_read_notify(struct qcom_glink *glink)
{
	struct glink_msg msg;

	msg.cmd = cpu_to_le16(RPM_CMD_READ_NOTIF);
	msg.param1 = 0;
	msg.param2 = 0;

	GLINK_INFO(glink->ilc, "send READ NOTIFY cmd\n");

	qcom_glink_tx_write(glink, &msg, sizeof(msg), NULL, 0);

	mbox_send_message(glink->mbox_chan, NULL);
	mbox_client_txdone(glink->mbox_chan, 0);
}

static int qcom_glink_tx(struct qcom_glink *glink,
static int qcom_glink_tx(struct qcom_glink *glink,
			 const void *hdr, size_t hlen,
			 const void *hdr, size_t hlen,
			 const void *data, size_t dlen, bool wait)
			 const void *data, size_t dlen, bool wait)
@@ -380,17 +401,27 @@ static int qcom_glink_tx(struct qcom_glink *glink,
			goto out;
			goto out;
		}
		}


		if (atomic_read(&glink->in_reset)) {
		if (!glink->sent_read_notify) {
			ret = -ECONNRESET;
			glink->sent_read_notify = true;
			goto out;
			qcom_glink_send_read_notify(glink);
		}
		}


		/* Wait without holding the tx_lock */
		/* Wait without holding the tx_lock */
		spin_unlock_irqrestore(&glink->tx_lock, flags);
		spin_unlock_irqrestore(&glink->tx_lock, flags);


		usleep_range(10000, 15000);
		wait_event_timeout(glink->tx_avail_notify,
				   (qcom_glink_tx_avail(glink) >= tlen
				   || atomic_read(&glink->in_reset)), 10 * HZ);


		spin_lock_irqsave(&glink->tx_lock, flags);
		spin_lock_irqsave(&glink->tx_lock, flags);

		if (atomic_read(&glink->in_reset)) {
			ret = -ECONNRESET;
			goto out;
		}

		if (qcom_glink_tx_avail(glink) >= tlen)
			glink->sent_read_notify = false;
	}
	}


	qcom_glink_tx_write(glink, hdr, hlen, data, dlen);
	qcom_glink_tx_write(glink, hdr, hlen, data, dlen);
@@ -1158,6 +1189,9 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data)
	unsigned int cmd;
	unsigned int cmd;
	int ret = 0;
	int ret = 0;


	/* To wakeup any blocking writers */
	wake_up_all(&glink->tx_avail_notify);

	for (;;) {
	for (;;) {
		avail = qcom_glink_rx_avail(glink);
		avail = qcom_glink_rx_avail(glink);
		if (avail < sizeof(msg))
		if (avail < sizeof(msg))
@@ -1904,6 +1938,9 @@ static void qcom_glink_notif_reset(void *data)
		return;
		return;
	atomic_inc(&glink->in_reset);
	atomic_inc(&glink->in_reset);


	/* To wakeup any blocking writers */
	wake_up_all(&glink->tx_avail_notify);

	spin_lock_irqsave(&glink->idr_lock, flags);
	spin_lock_irqsave(&glink->idr_lock, flags);
	idr_for_each_entry(&glink->lcids, channel, cid) {
	idr_for_each_entry(&glink->lcids, channel, cid) {
		wake_up(&channel->intent_req_event);
		wake_up(&channel->intent_req_event);
@@ -1952,6 +1989,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev,
	spin_lock_init(&glink->rx_lock);
	spin_lock_init(&glink->rx_lock);
	INIT_LIST_HEAD(&glink->rx_queue);
	INIT_LIST_HEAD(&glink->rx_queue);
	INIT_WORK(&glink->rx_work, qcom_glink_work);
	INIT_WORK(&glink->rx_work, qcom_glink_work);
	init_waitqueue_head(&glink->tx_avail_notify);


	spin_lock_init(&glink->idr_lock);
	spin_lock_init(&glink->idr_lock);
	idr_init(&glink->lcids);
	idr_init(&glink->lcids);