Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[firefly-linux-kernel-4.4.55.git] / drivers / mtd / mtdcore.c
index bbcba0dbd5c3062e7da07979fb9c42af98558b54..95c13b2ffa799e59f453e8a95813171cd56a13fc 100644 (file)
@@ -387,6 +387,14 @@ int add_mtd_device(struct mtd_info *mtd)
        struct mtd_notifier *not;
        int i, error;
 
+       /*
+        * May occur, for instance, on buggy drivers which call
+        * mtd_device_parse_register() multiple times on the same master MTD,
+        * especially with CONFIG_MTD_PARTITIONED_MASTER=y.
+        */
+       if (WARN_ONCE(mtd->backing_dev_info, "MTD already registered\n"))
+               return -EEXIST;
+
        mtd->backing_dev_info = &mtd_bdi;
 
        BUG_ON(mtd->writesize == 0);
@@ -588,9 +596,17 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
                else
                        ret = nr_parts;
        }
+       /* Didn't come up with either parsed OR fallback partitions */
+       if (ret < 0) {
+               pr_info("mtd: failed to find partitions; one or more parsers reports errors (%d)\n",
+                       ret);
+               /* Don't abort on errors; we can still use unpartitioned MTD */
+               ret = 0;
+       }
 
-       if (ret >= 0)
-               ret = mtd_add_device_partitions(mtd, real_parts, ret);
+       ret = mtd_add_device_partitions(mtd, real_parts, ret);
+       if (ret)
+               goto out;
 
        /*
         * FIXME: some drivers unfortunately call this function more than once.
@@ -600,11 +616,14 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
         * does cause problems with parse_mtd_partitions() above (e.g.,
         * cmdlineparts will register partitions more than once).
         */
+       WARN_ONCE(mtd->_reboot && mtd->reboot_notifier.notifier_call,
+                 "MTD already registered\n");
        if (mtd->_reboot && !mtd->reboot_notifier.notifier_call) {
                mtd->reboot_notifier.notifier_call = mtd_reboot_notifier;
                register_reboot_notifier(&mtd->reboot_notifier);
        }
 
+out:
        kfree(real_parts);
        return ret;
 }
@@ -1197,8 +1216,7 @@ EXPORT_SYMBOL_GPL(mtd_writev);
  */
 void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size)
 {
-       gfp_t flags = __GFP_NOWARN | __GFP_WAIT |
-                      __GFP_NORETRY | __GFP_NO_KSWAPD;
+       gfp_t flags = __GFP_NOWARN | __GFP_DIRECT_RECLAIM | __GFP_NORETRY;
        size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE);
        void *kbuf;