These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / mtd / ubi / block.c
index c9eb78f..ebf46ad 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/blk-mq.h>
 #include <linux/hdreg.h>
 #include <linux/scatterlist.h>
+#include <linux/idr.h>
 #include <asm/div64.h>
 
 #include "ubi-media.h"
@@ -161,7 +162,7 @@ static int __init ubiblock_set_param(const char *val,
        return 0;
 }
 
-static struct kernel_param_ops ubiblock_param_ops = {
+static const struct kernel_param_ops ubiblock_param_ops = {
        .set    = ubiblock_set_param,
 };
 module_param_cb(block, &ubiblock_param_ops, NULL, 0);
@@ -353,6 +354,8 @@ static struct blk_mq_ops ubiblock_mq_ops = {
        .map_queue      = blk_mq_map_queue,
 };
 
+static DEFINE_IDR(ubiblock_minor_idr);
+
 int ubiblock_create(struct ubi_volume_info *vi)
 {
        struct ubiblock *dev;
@@ -390,7 +393,13 @@ int ubiblock_create(struct ubi_volume_info *vi)
 
        gd->fops = &ubiblock_ops;
        gd->major = ubiblock_major;
-       gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id;
+       gd->first_minor = idr_alloc(&ubiblock_minor_idr, dev, 0, 0, GFP_KERNEL);
+       if (gd->first_minor < 0) {
+               dev_err(disk_to_dev(gd),
+                       "block: dynamic minor allocation failed");
+               ret = -ENODEV;
+               goto out_put_disk;
+       }
        gd->private_data = dev;
        sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id);
        set_capacity(gd, disk_capacity);
@@ -407,7 +416,7 @@ int ubiblock_create(struct ubi_volume_info *vi)
        ret = blk_mq_alloc_tag_set(&dev->tag_set);
        if (ret) {
                dev_err(disk_to_dev(dev->gd), "blk_mq_alloc_tag_set failed");
-               goto out_put_disk;
+               goto out_remove_minor;
        }
 
        dev->rq = blk_mq_init_queue(&dev->tag_set);
@@ -445,6 +454,8 @@ out_free_queue:
        blk_cleanup_queue(dev->rq);
 out_free_tags:
        blk_mq_free_tag_set(&dev->tag_set);
+out_remove_minor:
+       idr_remove(&ubiblock_minor_idr, gd->first_minor);
 out_put_disk:
        put_disk(dev->gd);
 out_free_dev:
@@ -463,6 +474,7 @@ static void ubiblock_cleanup(struct ubiblock *dev)
        blk_cleanup_queue(dev->rq);
        blk_mq_free_tag_set(&dev->tag_set);
        dev_info(disk_to_dev(dev->gd), "released");
+       idr_remove(&ubiblock_minor_idr, dev->gd->first_minor);
        put_disk(dev->gd);
 }