aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
authorOhad Ben-Cohen <ohad@wizery.com>2010-05-05 11:33:09 -0400
committerHiroshi DOYU <Hiroshi.DOYU@nokia.com>2010-08-04 08:50:17 -0400
commitb5bebe410204cf84337b54c372cceda2d6b27de6 (patch)
treeef64f9a9836c05d21c7e65d6d6429beb174956a6 /arch/arm/plat-omap
parent01072d8f4b9911047ef435a807cfd7223c94d94d (diff)
omap: mailbox: convert block api to kfifo
The underlying buffering implementation of mailbox is converted from block API to kfifo due to the simplicity and speed of kfifo. The default size of the kfifo buffer is set to 256 bytes. This value is configurable at compile time (via CONFIG_OMAP_MBOX_KFIFO_SIZE), and can be changed at runtime (via the mbox_kfifo_size module parameter). Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com> Signed-off-by: Hari Kanigeri <h-kanigeri2@ti.com> Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r--arch/arm/plat-omap/Kconfig9
-rw-r--r--arch/arm/plat-omap/include/plat/mailbox.h4
-rw-r--r--arch/arm/plat-omap/mailbox.c119
3 files changed, 64 insertions, 68 deletions
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 78b49a626d06..111d39a47ad1 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -106,6 +106,15 @@ config OMAP_MBOX_FWK
106 Say Y here if you want to use OMAP Mailbox framework support for 106 Say Y here if you want to use OMAP Mailbox framework support for
107 DSP, IVA1.0 and IVA2 in OMAP1/2/3. 107 DSP, IVA1.0 and IVA2 in OMAP1/2/3.
108 108
109config OMAP_MBOX_KFIFO_SIZE
110 int "Mailbox kfifo default buffer size (bytes)"
111 depends on OMAP_MBOX_FWK
112 default 256
113 help
114 Specify the default size of mailbox's kfifo buffers (bytes).
115 This can also be changed at runtime (via the mbox_kfifo_size
116 module parameter).
117
109config OMAP_IOMMU 118config OMAP_IOMMU
110 tristate 119 tristate
111 120
diff --git a/arch/arm/plat-omap/include/plat/mailbox.h b/arch/arm/plat-omap/include/plat/mailbox.h
index 729166b76a7c..0c3c4a5f4b42 100644
--- a/arch/arm/plat-omap/include/plat/mailbox.h
+++ b/arch/arm/plat-omap/include/plat/mailbox.h
@@ -5,8 +5,8 @@
5 5
6#include <linux/wait.h> 6#include <linux/wait.h>
7#include <linux/workqueue.h> 7#include <linux/workqueue.h>
8#include <linux/blkdev.h>
9#include <linux/interrupt.h> 8#include <linux/interrupt.h>
9#include <linux/kfifo.h>
10 10
11typedef u32 mbox_msg_t; 11typedef u32 mbox_msg_t;
12struct omap_mbox; 12struct omap_mbox;
@@ -42,7 +42,7 @@ struct omap_mbox_ops {
42 42
43struct omap_mbox_queue { 43struct omap_mbox_queue {
44 spinlock_t lock; 44 spinlock_t lock;
45 struct request_queue *queue; 45 struct kfifo fifo;
46 struct work_struct work; 46 struct work_struct work;
47 struct tasklet_struct tasklet; 47 struct tasklet_struct tasklet;
48 int (*callback)(void *); 48 int (*callback)(void *);
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
index 81076b54d37b..ec0e1596b4f3 100644
--- a/arch/arm/plat-omap/mailbox.c
+++ b/arch/arm/plat-omap/mailbox.c
@@ -21,11 +21,14 @@
21 * 21 *
22 */ 22 */
23 23
24#include <linux/kernel.h>
24#include <linux/module.h> 25#include <linux/module.h>
25#include <linux/interrupt.h> 26#include <linux/interrupt.h>
26#include <linux/device.h> 27#include <linux/device.h>
27#include <linux/delay.h> 28#include <linux/delay.h>
28#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/kfifo.h>
31#include <linux/err.h>
29 32
30#include <plat/mailbox.h> 33#include <plat/mailbox.h>
31 34
@@ -37,6 +40,10 @@ static bool rq_full;
37static int mbox_configured; 40static int mbox_configured;
38static DEFINE_MUTEX(mbox_configured_lock); 41static DEFINE_MUTEX(mbox_configured_lock);
39 42
43static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
44module_param(mbox_kfifo_size, uint, S_IRUGO);
45MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
46
40/* Mailbox FIFO handle functions */ 47/* Mailbox FIFO handle functions */
41static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) 48static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
42{ 49{
@@ -69,7 +76,7 @@ static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
69/* 76/*
70 * message sender 77 * message sender
71 */ 78 */
72static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) 79static int __mbox_poll_for_space(struct omap_mbox *mbox)
73{ 80{
74 int ret = 0, i = 1000; 81 int ret = 0, i = 1000;
75 82
@@ -80,49 +87,50 @@ static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
80 return -1; 87 return -1;
81 udelay(1); 88 udelay(1);
82 } 89 }
83 mbox_fifo_write(mbox, msg);
84 return ret; 90 return ret;
85} 91}
86 92
87
88int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) 93int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
89{ 94{
95 struct omap_mbox_queue *mq = mbox->txq;
96 int ret = 0, len;
90 97
91 struct request *rq; 98 spin_lock(&mq->lock);
92 struct request_queue *q = mbox->txq->queue;
93 99
94 rq = blk_get_request(q, WRITE, GFP_ATOMIC); 100 if (kfifo_avail(&mq->fifo) < sizeof(msg)) {
95 if (unlikely(!rq)) 101 ret = -ENOMEM;
96 return -ENOMEM; 102 goto out;
103 }
104
105 len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
106 WARN_ON(len != sizeof(msg));
97 107
98 blk_insert_request(q, rq, 0, (void *) msg);
99 tasklet_schedule(&mbox->txq->tasklet); 108 tasklet_schedule(&mbox->txq->tasklet);
100 109
101 return 0; 110out:
111 spin_unlock(&mq->lock);
112 return ret;
102} 113}
103EXPORT_SYMBOL(omap_mbox_msg_send); 114EXPORT_SYMBOL(omap_mbox_msg_send);
104 115
105static void mbox_tx_tasklet(unsigned long tx_data) 116static void mbox_tx_tasklet(unsigned long tx_data)
106{ 117{
107 int ret;
108 struct request *rq;
109 struct omap_mbox *mbox = (struct omap_mbox *)tx_data; 118 struct omap_mbox *mbox = (struct omap_mbox *)tx_data;
110 struct request_queue *q = mbox->txq->queue; 119 struct omap_mbox_queue *mq = mbox->txq;
111 120 mbox_msg_t msg;
112 while (1) { 121 int ret;
113
114 rq = blk_fetch_request(q);
115
116 if (!rq)
117 break;
118 122
119 ret = __mbox_msg_send(mbox, (mbox_msg_t)rq->special); 123 while (kfifo_len(&mq->fifo)) {
120 if (ret) { 124 if (__mbox_poll_for_space(mbox)) {
121 omap_mbox_enable_irq(mbox, IRQ_TX); 125 omap_mbox_enable_irq(mbox, IRQ_TX);
122 blk_requeue_request(q, rq); 126 break;
123 return;
124 } 127 }
125 blk_end_request_all(rq, 0); 128
129 ret = kfifo_out(&mq->fifo, (unsigned char *)&msg,
130 sizeof(msg));
131 WARN_ON(ret != sizeof(msg));
132
133 mbox_fifo_write(mbox, msg);
126 } 134 }
127} 135}
128 136
@@ -133,41 +141,21 @@ static void mbox_rx_work(struct work_struct *work)
133{ 141{
134 struct omap_mbox_queue *mq = 142 struct omap_mbox_queue *mq =
135 container_of(work, struct omap_mbox_queue, work); 143 container_of(work, struct omap_mbox_queue, work);
136 struct omap_mbox *mbox = mq->queue->queuedata;
137 struct request_queue *q = mbox->rxq->queue;
138 struct request *rq;
139 mbox_msg_t msg; 144 mbox_msg_t msg;
140 unsigned long flags; 145 int len;
141 146
142 while (1) { 147 while (kfifo_len(&mq->fifo) >= sizeof(msg)) {
143 spin_lock_irqsave(q->queue_lock, flags); 148 len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
144 rq = blk_fetch_request(q); 149 WARN_ON(len != sizeof(msg));
145 if (rq_full) {
146 omap_mbox_enable_irq(mbox, IRQ_RX);
147 rq_full = false;
148 }
149 spin_unlock_irqrestore(q->queue_lock, flags);
150 if (!rq)
151 break;
152 150
153 msg = (mbox_msg_t)rq->special; 151 if (mq->callback)
154 blk_end_request_all(rq, 0); 152 mq->callback((void *)msg);
155 if (mbox->rxq->callback)
156 mbox->rxq->callback((void *)msg);
157 } 153 }
158} 154}
159 155
160/* 156/*
161 * Mailbox interrupt handler 157 * Mailbox interrupt handler
162 */ 158 */
163static void mbox_txq_fn(struct request_queue *q)
164{
165}
166
167static void mbox_rxq_fn(struct request_queue *q)
168{
169}
170
171static void __mbox_tx_interrupt(struct omap_mbox *mbox) 159static void __mbox_tx_interrupt(struct omap_mbox *mbox)
172{ 160{
173 omap_mbox_disable_irq(mbox, IRQ_TX); 161 omap_mbox_disable_irq(mbox, IRQ_TX);
@@ -177,13 +165,12 @@ static void __mbox_tx_interrupt(struct omap_mbox *mbox)
177 165
178static void __mbox_rx_interrupt(struct omap_mbox *mbox) 166static void __mbox_rx_interrupt(struct omap_mbox *mbox)
179{ 167{
180 struct request *rq; 168 struct omap_mbox_queue *mq = mbox->rxq;
181 mbox_msg_t msg; 169 mbox_msg_t msg;
182 struct request_queue *q = mbox->rxq->queue; 170 int len;
183 171
184 while (!mbox_fifo_empty(mbox)) { 172 while (!mbox_fifo_empty(mbox)) {
185 rq = blk_get_request(q, WRITE, GFP_ATOMIC); 173 if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) {
186 if (unlikely(!rq)) {
187 omap_mbox_disable_irq(mbox, IRQ_RX); 174 omap_mbox_disable_irq(mbox, IRQ_RX);
188 rq_full = true; 175 rq_full = true;
189 goto nomem; 176 goto nomem;
@@ -191,8 +178,9 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
191 178
192 msg = mbox_fifo_read(mbox); 179 msg = mbox_fifo_read(mbox);
193 180
181 len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
182 WARN_ON(len != sizeof(msg));
194 183
195 blk_insert_request(q, rq, 0, (void *)msg);
196 if (mbox->ops->type == OMAP_MBOX_TYPE1) 184 if (mbox->ops->type == OMAP_MBOX_TYPE1)
197 break; 185 break;
198 } 186 }
@@ -217,11 +205,9 @@ static irqreturn_t mbox_interrupt(int irq, void *p)
217} 205}
218 206
219static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, 207static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
220 request_fn_proc *proc,
221 void (*work) (struct work_struct *), 208 void (*work) (struct work_struct *),
222 void (*tasklet)(unsigned long)) 209 void (*tasklet)(unsigned long))
223{ 210{
224 struct request_queue *q;
225 struct omap_mbox_queue *mq; 211 struct omap_mbox_queue *mq;
226 212
227 mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); 213 mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL);
@@ -230,11 +216,8 @@ static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
230 216
231 spin_lock_init(&mq->lock); 217 spin_lock_init(&mq->lock);
232 218
233 q = blk_init_queue(proc, &mq->lock); 219 if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL))
234 if (!q)
235 goto error; 220 goto error;
236 q->queuedata = mbox;
237 mq->queue = q;
238 221
239 if (work) 222 if (work)
240 INIT_WORK(&mq->work, work); 223 INIT_WORK(&mq->work, work);
@@ -249,7 +232,7 @@ error:
249 232
250static void mbox_queue_free(struct omap_mbox_queue *q) 233static void mbox_queue_free(struct omap_mbox_queue *q)
251{ 234{
252 blk_cleanup_queue(q->queue); 235 kfifo_free(&q->fifo);
253 kfree(q); 236 kfree(q);
254} 237}
255 238
@@ -279,14 +262,14 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
279 goto fail_request_irq; 262 goto fail_request_irq;
280 } 263 }
281 264
282 mq = mbox_queue_alloc(mbox, mbox_txq_fn, NULL, mbox_tx_tasklet); 265 mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
283 if (!mq) { 266 if (!mq) {
284 ret = -ENOMEM; 267 ret = -ENOMEM;
285 goto fail_alloc_txq; 268 goto fail_alloc_txq;
286 } 269 }
287 mbox->txq = mq; 270 mbox->txq = mq;
288 271
289 mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work, NULL); 272 mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL);
290 if (!mq) { 273 if (!mq) {
291 ret = -ENOMEM; 274 ret = -ENOMEM;
292 goto fail_alloc_rxq; 275 goto fail_alloc_rxq;
@@ -418,6 +401,10 @@ static int __init omap_mbox_init(void)
418 if (!mboxd) 401 if (!mboxd)
419 return -ENOMEM; 402 return -ENOMEM;
420 403
404 /* kfifo size sanity check: alignment and minimal size */
405 mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t));
406 mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, sizeof(mbox_msg_t));
407
421 return 0; 408 return 0;
422} 409}
423module_init(omap_mbox_init); 410module_init(omap_mbox_init);