OSDN Git Service

mmc: block: Simplify cleaning up the queue
authorAdrian Hunter <adrian.hunter@intel.com>
Wed, 29 Nov 2017 13:40:59 +0000 (15:40 +0200)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 11 Dec 2017 11:44:31 +0000 (12:44 +0100)
Use blk_cleanup_queue() to shutdown the queue when the driver is removed,
and instead get an extra reference to the queue to prevent the queue being
freed before the final mmc_blk_put().

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: Linus Walleij <linus.walleij@linaro.org>
drivers/mmc/core/block.c
drivers/mmc/core/queue.c

index ccfa98a..e44f6d9 100644 (file)
@@ -189,7 +189,7 @@ static void mmc_blk_put(struct mmc_blk_data *md)
        md->usage--;
        if (md->usage == 0) {
                int devidx = mmc_get_devidx(md->disk);
-               blk_cleanup_queue(md->queue.queue);
+               blk_put_queue(md->queue.queue);
                ida_simple_remove(&mmc_blk_ida, devidx);
                put_disk(md->disk);
                kfree(md);
@@ -2156,6 +2156,17 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
 
        md->queue.blkdata = md;
 
+       /*
+        * Keep an extra reference to the queue so that we can shutdown the
+        * queue (i.e. call blk_cleanup_queue()) while there are still
+        * references to the 'md'. The corresponding blk_put_queue() is in
+        * mmc_blk_put().
+        */
+       if (!blk_get_queue(md->queue.queue)) {
+               mmc_cleanup_queue(&md->queue);
+               goto err_putdisk;
+       }
+
        md->disk->major = MMC_BLOCK_MAJOR;
        md->disk->first_minor = devidx * perdev_minors;
        md->disk->fops = &mmc_bdops;
@@ -2471,10 +2482,6 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
                 * from being accepted.
                 */
                card = md->queue.card;
-               spin_lock_irq(md->queue.queue->queue_lock);
-               queue_flag_set(QUEUE_FLAG_BYPASS, md->queue.queue);
-               spin_unlock_irq(md->queue.queue->queue_lock);
-               blk_set_queue_dying(md->queue.queue);
                mmc_cleanup_queue(&md->queue);
                if (md->disk->flags & GENHD_FL_UP) {
                        device_remove_file(disk_to_dev(md->disk), &md->force_ro);
index 26f8da3..ae6d9da 100644 (file)
@@ -268,6 +268,8 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
        blk_start_queue(q);
        spin_unlock_irqrestore(q->queue_lock, flags);
 
+       blk_cleanup_queue(q);
+
        mq->card = NULL;
 }