aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSudeep Holla <sudeep.holla@arm.com>2015-07-31 06:48:05 -0400
committerJassi Brar <jaswinder.singh@linaro.org>2015-08-10 04:59:27 -0400
commit0cc67945ea5933d53db69606312cf52f553d1b81 (patch)
tree486e823aaccb3d7de2bd377af36b0bfdd6cdbf9f
parent63d5e127de8287c4ae80f43cda8cb9c06e612929 (diff)
mailbox: switch to hrtimer for tx_complete polling
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>
-rw-r--r--drivers/mailbox/mailbox.c27
-rw-r--r--include/linux/mailbox_controller.h7
2 files changed, 19 insertions, 15 deletions
diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
index c7fdb57fd166..6a4811f85705 100644
--- a/drivers/mailbox/mailbox.c
+++ b/drivers/mailbox/mailbox.c
@@ -26,8 +26,6 @@
26static LIST_HEAD(mbox_cons); 26static LIST_HEAD(mbox_cons);
27static DEFINE_MUTEX(con_mutex); 27static DEFINE_MUTEX(con_mutex);
28 28
29static void poll_txdone(unsigned long data);
30
31static int add_to_rbuf(struct mbox_chan *chan, void *mssg) 29static int add_to_rbuf(struct mbox_chan *chan, void *mssg)
32{ 30{
33 int idx; 31 int idx;
@@ -88,7 +86,9 @@ exit:
88 spin_unlock_irqrestore(&chan->lock, flags); 86 spin_unlock_irqrestore(&chan->lock, flags);
89 87
90 if (!err && (chan->txdone_method & TXDONE_BY_POLL)) 88 if (!err && (chan->txdone_method & TXDONE_BY_POLL))
91 poll_txdone((unsigned long)chan->mbox); 89 /* kick start the timer immediately to avoid delays */
90 hrtimer_start(&chan->mbox->poll_hrt, ktime_set(0, 0),
91 HRTIMER_MODE_REL);
92} 92}
93 93
94static void tx_tick(struct mbox_chan *chan, int r) 94static void tx_tick(struct mbox_chan *chan, int r)
@@ -112,9 +112,10 @@ static void tx_tick(struct mbox_chan *chan, int r)
112 complete(&chan->tx_complete); 112 complete(&chan->tx_complete);
113} 113}
114 114
115static void poll_txdone(unsigned long data) 115static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer)
116{ 116{
117 struct mbox_controller *mbox = (struct mbox_controller *)data; 117 struct mbox_controller *mbox =
118 container_of(hrtimer, struct mbox_controller, poll_hrt);
118 bool txdone, resched = false; 119 bool txdone, resched = false;
119 int i; 120 int i;
120 121
@@ -130,9 +131,11 @@ static void poll_txdone(unsigned long data)
130 } 131 }
131 } 132 }
132 133
133 if (resched) 134 if (resched) {
134 mod_timer(&mbox->poll, jiffies + 135 hrtimer_forward_now(hrtimer, ms_to_ktime(mbox->txpoll_period));
135 msecs_to_jiffies(mbox->txpoll_period)); 136 return HRTIMER_RESTART;
137 }
138 return HRTIMER_NORESTART;
136} 139}
137 140
138/** 141/**
@@ -451,9 +454,9 @@ int mbox_controller_register(struct mbox_controller *mbox)
451 txdone = TXDONE_BY_ACK; 454 txdone = TXDONE_BY_ACK;
452 455
453 if (txdone == TXDONE_BY_POLL) { 456 if (txdone == TXDONE_BY_POLL) {
454 mbox->poll.function = &poll_txdone; 457 hrtimer_init(&mbox->poll_hrt, CLOCK_MONOTONIC,
455 mbox->poll.data = (unsigned long)mbox; 458 HRTIMER_MODE_REL);
456 init_timer(&mbox->poll); 459 mbox->poll_hrt.function = txdone_hrtimer;
457 } 460 }
458 461
459 for (i = 0; i < mbox->num_chans; i++) { 462 for (i = 0; i < mbox->num_chans; i++) {
@@ -495,7 +498,7 @@ void mbox_controller_unregister(struct mbox_controller *mbox)
495 mbox_free_channel(&mbox->chans[i]); 498 mbox_free_channel(&mbox->chans[i]);
496 499
497 if (mbox->txdone_poll) 500 if (mbox->txdone_poll)
498 del_timer_sync(&mbox->poll); 501 hrtimer_cancel(&mbox->poll_hrt);
499 502
500 mutex_unlock(&con_mutex); 503 mutex_unlock(&con_mutex);
501} 504}
diff --git a/include/linux/mailbox_controller.h b/include/linux/mailbox_controller.h
index 68c42454439b..74deadb42d76 100644
--- a/include/linux/mailbox_controller.h
+++ b/include/linux/mailbox_controller.h
@@ -9,7 +9,7 @@
9 9
10#include <linux/of.h> 10#include <linux/of.h>
11#include <linux/types.h> 11#include <linux/types.h>
12#include <linux/timer.h> 12#include <linux/hrtimer.h>
13#include <linux/device.h> 13#include <linux/device.h>
14#include <linux/completion.h> 14#include <linux/completion.h>
15 15
@@ -67,7 +67,8 @@ struct mbox_chan_ops {
67 * @txpoll_period: If 'txdone_poll' is in effect, the API polls for 67 * @txpoll_period: If 'txdone_poll' is in effect, the API polls for
68 * last TX's status after these many millisecs 68 * last TX's status after these many millisecs
69 * @of_xlate: Controller driver specific mapping of channel via DT 69 * @of_xlate: Controller driver specific mapping of channel via DT
70 * @poll: API private. Used to poll for TXDONE on all channels. 70 * @poll_hrt: API private. hrtimer used to poll for TXDONE on all
71 * channels.
71 * @node: API private. To hook into list of controllers. 72 * @node: API private. To hook into list of controllers.
72 */ 73 */
73struct mbox_controller { 74struct mbox_controller {
@@ -81,7 +82,7 @@ struct mbox_controller {
81 struct mbox_chan *(*of_xlate)(struct mbox_controller *mbox, 82 struct mbox_chan *(*of_xlate)(struct mbox_controller *mbox,
82 const struct of_phandle_args *sp); 83 const struct of_phandle_args *sp);
83 /* Internal to API */ 84 /* Internal to API */
84 struct timer_list poll; 85 struct hrtimer poll_hrt;
85 struct list_head node; 86 struct list_head node;
86}; 87};
87 88