]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
mailbox: switch to hrtimer for tx_complete polling
authorSudeep Holla <sudeep.holla@arm.com>
Fri, 31 Jul 2015 10:48:05 +0000 (11:48 +0100)
committerJassi Brar <jaswinder.singh@linaro.org>
Mon, 10 Aug 2015 08:59:27 +0000 (14:29 +0530)
The mailbox core uses jiffy based timer to handle polling for the
transmit completion. If the client/protocol have/support notification
of the last packet transmit completion via ACK packet, then we tick the
Tx state machine immediately in the callback. However if the client
doesn't support that mechanism we might end-up waiting for atleast a
jiffy even though the remote is ready to receive the next request.

This patch switches the timer used for that polling from jiffy-based
to hrtimer-based so that we can support polling at much higher time
resolution.

Reported-and-suggested-by: Juri Lelli <Juri.Lelli@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
drivers/mailbox/mailbox.c
include/linux/mailbox_controller.h

index c7fdb57fd166cbf9cb8a0035c56f67a75ff8aa0a..6a4811f857056aaa64baff75265902b59be12ac9 100644 (file)
@@ -26,8 +26,6 @@
 static LIST_HEAD(mbox_cons);
 static DEFINE_MUTEX(con_mutex);
 
-static void poll_txdone(unsigned long data);
-
 static int add_to_rbuf(struct mbox_chan *chan, void *mssg)
 {
        int idx;
@@ -88,7 +86,9 @@ static void msg_submit(struct mbox_chan *chan)
        spin_unlock_irqrestore(&chan->lock, flags);
 
        if (!err && (chan->txdone_method & TXDONE_BY_POLL))
-               poll_txdone((unsigned long)chan->mbox);
+               /* kick start the timer immediately to avoid delays */
+               hrtimer_start(&chan->mbox->poll_hrt, ktime_set(0, 0),
+                             HRTIMER_MODE_REL);
 }
 
 static void tx_tick(struct mbox_chan *chan, int r)
@@ -112,9 +112,10 @@ static void tx_tick(struct mbox_chan *chan, int r)
                complete(&chan->tx_complete);
 }
 
-static void poll_txdone(unsigned long data)
+static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer)
 {
-       struct mbox_controller *mbox = (struct mbox_controller *)data;
+       struct mbox_controller *mbox =
+               container_of(hrtimer, struct mbox_controller, poll_hrt);
        bool txdone, resched = false;
        int i;
 
@@ -130,9 +131,11 @@ static void poll_txdone(unsigned long data)
                }
        }
 
-       if (resched)
-               mod_timer(&mbox->poll, jiffies +
-                               msecs_to_jiffies(mbox->txpoll_period));
+       if (resched) {
+               hrtimer_forward_now(hrtimer, ms_to_ktime(mbox->txpoll_period));
+               return HRTIMER_RESTART;
+       }
+       return HRTIMER_NORESTART;
 }
 
 /**
@@ -451,9 +454,9 @@ int mbox_controller_register(struct mbox_controller *mbox)
                txdone = TXDONE_BY_ACK;
 
        if (txdone == TXDONE_BY_POLL) {
-               mbox->poll.function = &poll_txdone;
-               mbox->poll.data = (unsigned long)mbox;
-               init_timer(&mbox->poll);
+               hrtimer_init(&mbox->poll_hrt, CLOCK_MONOTONIC,
+                            HRTIMER_MODE_REL);
+               mbox->poll_hrt.function = txdone_hrtimer;
        }
 
        for (i = 0; i < mbox->num_chans; i++) {
@@ -495,7 +498,7 @@ void mbox_controller_unregister(struct mbox_controller *mbox)
                mbox_free_channel(&mbox->chans[i]);
 
        if (mbox->txdone_poll)
-               del_timer_sync(&mbox->poll);
+               hrtimer_cancel(&mbox->poll_hrt);
 
        mutex_unlock(&con_mutex);
 }
index 68c42454439be372caba99424ef6a57bac5f5c2d..74deadb42d76747e8f8f66b32bc839b052ed20a8 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <linux/of.h>
 #include <linux/types.h>
-#include <linux/timer.h>
+#include <linux/hrtimer.h>
 #include <linux/device.h>
 #include <linux/completion.h>
 
@@ -67,7 +67,8 @@ struct mbox_chan_ops {
  * @txpoll_period:     If 'txdone_poll' is in effect, the API polls for
  *                     last TX's status after these many millisecs
  * @of_xlate:          Controller driver specific mapping of channel via DT
- * @poll:              API private. Used to poll for TXDONE on all channels.
+ * @poll_hrt:          API private. hrtimer used to poll for TXDONE on all
+ *                     channels.
  * @node:              API private. To hook into list of controllers.
  */
 struct mbox_controller {
@@ -81,7 +82,7 @@ struct mbox_controller {
        struct mbox_chan *(*of_xlate)(struct mbox_controller *mbox,
                                      const struct of_phandle_args *sp);
        /* Internal to API */
-       struct timer_list poll;
+       struct hrtimer poll_hrt;
        struct list_head node;
 };