Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[cascardo/linux.git] / drivers / mtd / mtdcore.c
index 11883bd..d172195 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/gfp.h>
 #include <linux/slab.h>
 #include <linux/reboot.h>
+#include <linux/kconfig.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -501,6 +502,29 @@ out_error:
        return ret;
 }
 
+static int mtd_add_device_partitions(struct mtd_info *mtd,
+                                    struct mtd_partition *real_parts,
+                                    int nbparts)
+{
+       int ret;
+
+       if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
+               ret = add_mtd_device(mtd);
+               if (ret == 1)
+                       return -ENODEV;
+       }
+
+       if (nbparts > 0) {
+               ret = add_mtd_partitions(mtd, real_parts, nbparts);
+               if (ret && IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
+                       del_mtd_device(mtd);
+               return ret;
+       }
+
+       return 0;
+}
+
+
 /**
  * mtd_device_parse_register - parse partitions and register an MTD device.
  *
@@ -523,7 +547,8 @@ out_error:
  *   found this functions tries to fallback to information specified in
  *   @parts/@nr_parts.
  * * If any partitioning info was found, this function registers the found
- *   partitions.
+ *   partitions. If the MTD_PARTITIONED_MASTER option is set, then the device
+ *   as a whole is registered first.
  * * If no partitions were found this function just registers the MTD device
  *   @mtd and exits.
  *
@@ -534,27 +559,21 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
                              const struct mtd_partition *parts,
                              int nr_parts)
 {
-       int err;
-       struct mtd_partition *real_parts;
+       int ret;
+       struct mtd_partition *real_parts = NULL;
 
-       err = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
-       if (err <= 0 && nr_parts && parts) {
+       ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
+       if (ret <= 0 && nr_parts && parts) {
                real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
                                     GFP_KERNEL);
                if (!real_parts)
-                       err = -ENOMEM;
+                       ret = -ENOMEM;
                else
-                       err = nr_parts;
+                       ret = nr_parts;
        }
 
-       if (err > 0) {
-               err = add_mtd_partitions(mtd, real_parts, err);
-               kfree(real_parts);
-       } else if (err == 0) {
-               err = add_mtd_device(mtd);
-               if (err == 1)
-                       err = -ENODEV;
-       }
+       if (ret >= 0)
+               ret = mtd_add_device_partitions(mtd, real_parts, ret);
 
        /*
         * FIXME: some drivers unfortunately call this function more than once.
@@ -569,7 +588,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
                register_reboot_notifier(&mtd->reboot_notifier);
        }
 
-       return err;
+       kfree(real_parts);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_device_parse_register);