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.

Signed-off-by: Deepak Kumar Singh <deesin@codeaurora.org>
Signed-off-by: Arun Kumar Neelakantam <aneela@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Link: https://lore.kernel.org/r/1596086296-28529-7-git-send-email-deesin@codeaurora.org
This commit is contained in:
Arun Kumar Neelakantam 2020-07-30 10:48:16 +05:30 коммит произвёл Bjorn Andersson
Родитель 343ba27b6f
Коммит b16a37e184
1 изменённых файлов: 35 добавлений и 1 удалений

Просмотреть файл

@ -92,6 +92,8 @@ struct glink_core_rx_intent {
* @rcids: idr of all channels with a known remote channel id
* @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
*/
struct qcom_glink {
struct device *dev;
@ -118,6 +120,8 @@ struct qcom_glink {
unsigned long features;
bool intentless;
wait_queue_head_t tx_avail_notify;
bool sent_read_notify;
};
enum {
@ -301,6 +305,20 @@ static void qcom_glink_tx_write(struct qcom_glink *glink,
glink->tx_pipe->write(glink->tx_pipe, hdr, hlen, data, dlen);
}
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;
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)
@ -321,12 +339,21 @@ static int qcom_glink_tx(struct qcom_glink *glink,
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, 10 * HZ);
spin_lock_irqsave(&glink->tx_lock, flags);
if (qcom_glink_tx_avail(glink) >= tlen)
glink->sent_read_notify = false;
}
qcom_glink_tx_write(glink, hdr, hlen, data, dlen);
@ -986,6 +1013,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))
@ -1540,6 +1570,9 @@ static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid)
struct glink_channel *channel;
unsigned long flags;
/* To wakeup any blocking writers */
wake_up_all(&glink->tx_avail_notify);
spin_lock_irqsave(&glink->idr_lock, flags);
channel = idr_find(&glink->lcids, lcid);
if (WARN(!channel, "close ack on unknown channel\n")) {
@ -1710,6 +1743,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);