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: Arun Kumar Neelakantam <aneela@codeaurora.org>
This commit is contained in:
Arun Kumar Neelakantam 2020-02-17 12:14:21 +05:30 committed by Gerrit - the friendly Code Review server
parent 84b56d3ab5
commit 17a12f2a90

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* 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>
@ -121,6 +121,8 @@ struct glink_core_rx_intent {
* @in_reset: reset status of this edge
* @features: remote features
* @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
*/
struct qcom_glink {
@ -154,6 +156,9 @@ struct qcom_glink {
bool intentless;
wait_queue_head_t tx_avail_notify;
bool sent_read_notify;
void *ilc;
};
@ -357,6 +362,22 @@ static void qcom_glink_pipe_reset(struct qcom_glink *glink)
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,
const void *hdr, size_t hlen,
const void *data, size_t dlen, bool wait)
@ -380,17 +401,27 @@ static int qcom_glink_tx(struct qcom_glink *glink,
goto out;
}
if (atomic_read(&glink->in_reset)) {
ret = -ECONNRESET;
goto out;
if (!glink->sent_read_notify) {
glink->sent_read_notify = true;
qcom_glink_send_read_notify(glink);
}
/* Wait without holding the tx_lock */
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);
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);
@ -1158,6 +1189,9 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data)
unsigned int cmd;
int ret = 0;
/* To wakeup any blocking writers */
wake_up_all(&glink->tx_avail_notify);
for (;;) {
avail = qcom_glink_rx_avail(glink);
if (avail < sizeof(msg))
@ -1904,6 +1938,9 @@ static void qcom_glink_notif_reset(void *data)
return;
atomic_inc(&glink->in_reset);
/* To wakeup any blocking writers */
wake_up_all(&glink->tx_avail_notify);
spin_lock_irqsave(&glink->idr_lock, flags);
idr_for_each_entry(&glink->lcids, channel, cid) {
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);
INIT_LIST_HEAD(&glink->rx_queue);
INIT_WORK(&glink->rx_work, qcom_glink_work);
init_waitqueue_head(&glink->tx_avail_notify);
spin_lock_init(&glink->idr_lock);
idr_init(&glink->lcids);