]> www.infradead.org Git - users/willy/xarray.git/commitdiff
rpmsg: glink: Send READ_NOTIFY command in FIFO full case
authorArun Kumar Neelakantam <aneela@codeaurora.org>
Thu, 30 Jul 2020 05:18:16 +0000 (10:48 +0530)
committerBjorn Andersson <bjorn.andersson@linaro.org>
Fri, 15 Oct 2021 16:02:11 +0000 (11:02 -0500)
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
drivers/rpmsg/qcom_glink_native.c

index c1207aa88bdfc633375164b5505b43623f8cfd59..3f377a795b33151fa430086ee93432e98d8c90f7 100644 (file)
@@ -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);