*
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/kfifo.h>
+#include <linux/err.h>
 
 #include <plat/mailbox.h>
 
 static int mbox_configured;
 static DEFINE_MUTEX(mbox_configured_lock);
 
+static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
+module_param(mbox_kfifo_size, uint, S_IRUGO);
+MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
+
 /* Mailbox FIFO handle functions */
 static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
 {
 /*
  * message sender
  */
-static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
+static int __mbox_poll_for_space(struct omap_mbox *mbox)
 {
        int ret = 0, i = 1000;
 
                        return -1;
                udelay(1);
        }
-       mbox_fifo_write(mbox, msg);
        return ret;
 }
 
-
 int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
 {
+       struct omap_mbox_queue *mq = mbox->txq;
+       int ret = 0, len;
 
-       struct request *rq;
-       struct request_queue *q = mbox->txq->queue;
+       spin_lock(&mq->lock);
 
-       rq = blk_get_request(q, WRITE, GFP_ATOMIC);
-       if (unlikely(!rq))
-               return -ENOMEM;
+       if (kfifo_avail(&mq->fifo) < sizeof(msg)) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
+       WARN_ON(len != sizeof(msg));
 
-       blk_insert_request(q, rq, 0, (void *) msg);
        tasklet_schedule(&mbox->txq->tasklet);
 
-       return 0;
+out:
+       spin_unlock(&mq->lock);
+       return ret;
 }
 EXPORT_SYMBOL(omap_mbox_msg_send);
 
 static void mbox_tx_tasklet(unsigned long tx_data)
 {
-       int ret;
-       struct request *rq;
        struct omap_mbox *mbox = (struct omap_mbox *)tx_data;
-       struct request_queue *q = mbox->txq->queue;
-
-       while (1) {
-
-               rq = blk_fetch_request(q);
-
-               if (!rq)
-                       break;
+       struct omap_mbox_queue *mq = mbox->txq;
+       mbox_msg_t msg;
+       int ret;
 
-               ret = __mbox_msg_send(mbox, (mbox_msg_t)rq->special);
-               if (ret) {
+       while (kfifo_len(&mq->fifo)) {
+               if (__mbox_poll_for_space(mbox)) {
                        omap_mbox_enable_irq(mbox, IRQ_TX);
-                       blk_requeue_request(q, rq);
-                       return;
+                       break;
                }
-               blk_end_request_all(rq, 0);
+
+               ret = kfifo_out(&mq->fifo, (unsigned char *)&msg,
+                                                               sizeof(msg));
+               WARN_ON(ret != sizeof(msg));
+
+               mbox_fifo_write(mbox, msg);
        }
 }
 
 {
        struct omap_mbox_queue *mq =
                        container_of(work, struct omap_mbox_queue, work);
-       struct omap_mbox *mbox = mq->queue->queuedata;
-       struct request_queue *q = mbox->rxq->queue;
-       struct request *rq;
        mbox_msg_t msg;
-       unsigned long flags;
-
-       while (1) {
-               spin_lock_irqsave(q->queue_lock, flags);
-               rq = blk_fetch_request(q);
-               if (rq_full) {
-                       omap_mbox_enable_irq(mbox, IRQ_RX);
-                       rq_full = false;
-               }
-               spin_unlock_irqrestore(q->queue_lock, flags);
-               if (!rq)
-                       break;
+       int len;
+
+       while (kfifo_len(&mq->fifo) >= sizeof(msg)) {
+               len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
+               WARN_ON(len != sizeof(msg));
 
-               msg = (mbox_msg_t)rq->special;
-               blk_end_request_all(rq, 0);
-               if (mbox->rxq->callback)
-                       mbox->rxq->callback((void *)msg);
+               if (mq->callback)
+                       mq->callback((void *)msg);
        }
 }
 
 /*
  * Mailbox interrupt handler
  */
-static void mbox_txq_fn(struct request_queue *q)
-{
-}
-
-static void mbox_rxq_fn(struct request_queue *q)
-{
-}
-
 static void __mbox_tx_interrupt(struct omap_mbox *mbox)
 {
        omap_mbox_disable_irq(mbox, IRQ_TX);
 
 static void __mbox_rx_interrupt(struct omap_mbox *mbox)
 {
-       struct request *rq;
+       struct omap_mbox_queue *mq = mbox->rxq;
        mbox_msg_t msg;
-       struct request_queue *q = mbox->rxq->queue;
+       int len;
 
        while (!mbox_fifo_empty(mbox)) {
-               rq = blk_get_request(q, WRITE, GFP_ATOMIC);
-               if (unlikely(!rq)) {
+               if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) {
                        omap_mbox_disable_irq(mbox, IRQ_RX);
                        rq_full = true;
                        goto nomem;
 
                msg = mbox_fifo_read(mbox);
 
+               len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
+               WARN_ON(len != sizeof(msg));
 
-               blk_insert_request(q, rq, 0, (void *)msg);
                if (mbox->ops->type == OMAP_MBOX_TYPE1)
                        break;
        }
 }
 
 static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
-                                       request_fn_proc *proc,
                                        void (*work) (struct work_struct *),
                                        void (*tasklet)(unsigned long))
 {
-       struct request_queue *q;
        struct omap_mbox_queue *mq;
 
        mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL);
 
        spin_lock_init(&mq->lock);
 
-       q = blk_init_queue(proc, &mq->lock);
-       if (!q)
+       if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL))
                goto error;
-       q->queuedata = mbox;
-       mq->queue = q;
 
        if (work)
                INIT_WORK(&mq->work, work);
 
 static void mbox_queue_free(struct omap_mbox_queue *q)
 {
-       blk_cleanup_queue(q->queue);
+       kfifo_free(&q->fifo);
        kfree(q);
 }
 
                goto fail_request_irq;
        }
 
-       mq = mbox_queue_alloc(mbox, mbox_txq_fn, NULL, mbox_tx_tasklet);
+       mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
        if (!mq) {
                ret = -ENOMEM;
                goto fail_alloc_txq;
        }
        mbox->txq = mq;
 
-       mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work, NULL);
+       mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL);
        if (!mq) {
                ret = -ENOMEM;
                goto fail_alloc_rxq;
        if (!mboxd)
                return -ENOMEM;
 
+       /* kfifo size sanity check: alignment and minimal size */
+       mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t));
+       mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, sizeof(mbox_msg_t));
+
        return 0;
 }
 module_init(omap_mbox_init);