Skip to content

Commit

Permalink
rpmsg: glink: Send READ_NOTIFY command in FIFO full case
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Arun Kumar Neelakantam authored and Bjorn Andersson committed Oct 15, 2021
1 parent 343ba27 commit b16a37e
Showing 1 changed file with 35 additions and 1 deletion.
36 changes: 35 additions & 1 deletion drivers/rpmsg/qcom_glink_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -118,6 +120,8 @@ struct qcom_glink {
unsigned long features;

bool intentless;
wait_queue_head_t tx_avail_notify;
bool sent_read_notify;
};

enum {
Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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")) {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit b16a37e

Please sign in to comment.