mmc: queue: add a second mmc queue request member
authorPer Forlin <per.forlin@linaro.org>
Fri, 1 Jul 2011 16:55:31 +0000 (18:55 +0200)
committerChris Ball <cjb@laptop.org>
Wed, 20 Jul 2011 21:21:15 +0000 (17:21 -0400)
Add an additional mmc queue request instance to make way for two active
block requests. One request may be active while the other request is
being prepared.

Signed-off-by: Per Forlin <per.forlin@linaro.org>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Venkatraman S <svenkatr@ti.com>
Tested-by: Sourav Poddar <sourav.poddar@ti.com>
Tested-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Chris Ball <cjb@laptop.org>
drivers/mmc/card/queue.c
drivers/mmc/card/queue.h

index 9122ff5f39c8e91e04631cb6d7ab8572c3887039..a38d310f503028f3c2094192fcd8fe434a37a4e6 100644 (file)
@@ -153,6 +153,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
        u64 limit = BLK_BOUNCE_HIGH;
        int ret;
        struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
+       struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
 
        if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
                limit = *mmc_dev(host)->dma_mask;
@@ -163,7 +164,9 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
                return -ENOMEM;
 
        memset(&mq->mqrq_cur, 0, sizeof(mq->mqrq_cur));
+       memset(&mq->mqrq_prev, 0, sizeof(mq->mqrq_prev));
        mq->mqrq_cur = mqrq_cur;
+       mq->mqrq_prev = mqrq_prev;
        mq->queue->queuedata = mq;
 
        blk_queue_prep_rq(mq->queue, mmc_prep_request);
@@ -191,9 +194,17 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
                                        "allocate bounce cur buffer\n",
                                        mmc_card_name(card));
                        }
+                       mqrq_prev->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+                       if (!mqrq_prev->bounce_buf) {
+                               printk(KERN_WARNING "%s: unable to "
+                                       "allocate bounce prev buffer\n",
+                                       mmc_card_name(card));
+                               kfree(mqrq_cur->bounce_buf);
+                               mqrq_cur->bounce_buf = NULL;
+                       }
                }
 
-               if (mqrq_cur->bounce_buf) {
+               if (mqrq_cur->bounce_buf && mqrq_prev->bounce_buf) {
                        blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
                        blk_queue_max_hw_sectors(mq->queue, bouncesz / 512);
                        blk_queue_max_segments(mq->queue, bouncesz / 512);
@@ -208,11 +219,19 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
                        if (ret)
                                goto cleanup_queue;
 
+                       mqrq_prev->sg = mmc_alloc_sg(1, &ret);
+                       if (ret)
+                               goto cleanup_queue;
+
+                       mqrq_prev->bounce_sg =
+                               mmc_alloc_sg(bouncesz / 512, &ret);
+                       if (ret)
+                               goto cleanup_queue;
                }
        }
 #endif
 
-       if (!mqrq_cur->bounce_buf) {
+       if (!mqrq_cur->bounce_buf && !mqrq_prev->bounce_buf) {
                blk_queue_bounce_limit(mq->queue, limit);
                blk_queue_max_hw_sectors(mq->queue,
                        min(host->max_blk_count, host->max_req_size / 512));
@@ -223,6 +242,10 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
                if (ret)
                        goto cleanup_queue;
 
+
+               mqrq_prev->sg = mmc_alloc_sg(host->max_segs, &ret);
+               if (ret)
+                       goto cleanup_queue;
        }
 
        sema_init(&mq->thread_sem, 1);
@@ -239,6 +262,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
  free_bounce_sg:
        kfree(mqrq_cur->bounce_sg);
        mqrq_cur->bounce_sg = NULL;
+       kfree(mqrq_prev->bounce_sg);
+       mqrq_prev->bounce_sg = NULL;
 
  cleanup_queue:
        kfree(mqrq_cur->sg);
@@ -246,6 +271,11 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
        kfree(mqrq_cur->bounce_buf);
        mqrq_cur->bounce_buf = NULL;
 
+       kfree(mqrq_prev->sg);
+       mqrq_prev->sg = NULL;
+       kfree(mqrq_prev->bounce_buf);
+       mqrq_prev->bounce_buf = NULL;
+
        blk_cleanup_queue(mq->queue);
        return ret;
 }
@@ -255,6 +285,7 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
        struct request_queue *q = mq->queue;
        unsigned long flags;
        struct mmc_queue_req *mqrq_cur = mq->mqrq_cur;
+       struct mmc_queue_req *mqrq_prev = mq->mqrq_prev;
 
        /* Make sure the queue isn't suspended, as that will deadlock */
        mmc_queue_resume(mq);
@@ -277,6 +308,15 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
        kfree(mqrq_cur->bounce_buf);
        mqrq_cur->bounce_buf = NULL;
 
+       kfree(mqrq_prev->bounce_sg);
+       mqrq_prev->bounce_sg = NULL;
+
+       kfree(mqrq_prev->sg);
+       mqrq_prev->sg = NULL;
+
+       kfree(mqrq_prev->bounce_buf);
+       mqrq_prev->bounce_buf = NULL;
+
        mq->card = NULL;
 }
 EXPORT_SYMBOL(mmc_cleanup_queue);
index c1a69ac6fff054da3c52791e1b5348d822a94558..1a637d2e2ca693d298570c875e52c248bd0028d9 100644 (file)
@@ -29,8 +29,9 @@ struct mmc_queue {
        int                     (*issue_fn)(struct mmc_queue *, struct request *);
        void                    *data;
        struct request_queue    *queue;
-       struct mmc_queue_req    mqrq[1];
+       struct mmc_queue_req    mqrq[2];
        struct mmc_queue_req    *mqrq_cur;
+       struct mmc_queue_req    *mqrq_prev;
 };
 
 extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,