mmc: block: Convert to IDA for partition device indexes
authorUlf Hansson <ulf.hansson@linaro.org>
Thu, 7 Apr 2016 12:36:46 +0000 (14:36 +0200)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 2 May 2016 08:33:37 +0000 (10:33 +0200)
Instead of using an mmc specific implementation to deal with indexes
through a BITMAP, let's convert to use the IDA library.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/card/block.c

index 9aaf22e676c4b3a1a9248e4824d26711623d3122..9ce67925577504db95294532b1b003cb32317641 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/capability.h>
 #include <linux/compat.h>
 #include <linux/pm_runtime.h>
+#include <linux/idr.h>
 
 #include <linux/mmc/ioctl.h>
 #include <linux/mmc/card.h>
@@ -78,14 +79,14 @@ static int perdev_minors = CONFIG_MMC_BLOCK_MINORS;
 /*
  * We've only got one major, so number of mmcblk devices is
  * limited to (1 << 20) / number of minors per device.  It is also
- * currently limited by the size of the static bitmaps below.
+ * limited by the MAX_DEVICES below.
  */
 static int max_devices;
 
 #define MAX_DEVICES 256
 
-/* TODO: Replace these with struct ida */
-static DECLARE_BITMAP(dev_use, MAX_DEVICES);
+static DEFINE_IDA(mmc_blk_ida);
+static DEFINE_SPINLOCK(mmc_blk_lock);
 
 /*
  * There is one mmc_blk_data per slot.
@@ -178,7 +179,9 @@ static void mmc_blk_put(struct mmc_blk_data *md)
                int devidx = mmc_get_devidx(md->disk);
                blk_cleanup_queue(md->queue.queue);
 
-               __clear_bit(devidx, dev_use);
+               spin_lock(&mmc_blk_lock);
+               ida_remove(&mmc_blk_ida, devidx);
+               spin_unlock(&mmc_blk_lock);
 
                put_disk(md->disk);
                kfree(md);
@@ -2189,10 +2192,23 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
        struct mmc_blk_data *md;
        int devidx, ret;
 
-       devidx = find_first_zero_bit(dev_use, max_devices);
-       if (devidx >= max_devices)
-               return ERR_PTR(-ENOSPC);
-       __set_bit(devidx, dev_use);
+again:
+       if (!ida_pre_get(&mmc_blk_ida, GFP_KERNEL))
+               return ERR_PTR(-ENOMEM);
+
+       spin_lock(&mmc_blk_lock);
+       ret = ida_get_new(&mmc_blk_ida, &devidx);
+       spin_unlock(&mmc_blk_lock);
+
+       if (ret == -EAGAIN)
+               goto again;
+       else if (ret)
+               return ERR_PTR(ret);
+
+       if (devidx >= max_devices) {
+               ret = -ENOSPC;
+               goto out;
+       }
 
        md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
        if (!md) {
@@ -2289,7 +2305,9 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
  err_kfree:
        kfree(md);
  out:
-       __clear_bit(devidx, dev_use);
+       spin_lock(&mmc_blk_lock);
+       ida_remove(&mmc_blk_ida, devidx);
+       spin_unlock(&mmc_blk_lock);
        return ERR_PTR(ret);
 }