diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-01-20 14:01:31 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-01-20 14:01:31 -0300 |
commit | b4b7ff4b08e691656c9d77c758fc355833128ac0 (patch) | |
tree | 82fcb00e6b918026dc9f2d1f05ed8eee83874cc0 /drivers/mtd/mtdcore.c | |
parent | 35acfa0fc609f2a2cd95cef4a6a9c3a5c38f1778 (diff) |
Linux-libre 4.4-gnupck-4.4-gnu
Diffstat (limited to 'drivers/mtd/mtdcore.c')
-rw-r--r-- | drivers/mtd/mtdcore.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 8bbbb751b..ffa288474 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -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); @@ -430,7 +438,7 @@ int add_mtd_device(struct mtd_info *mtd) } /* Caller should have set dev.parent to match the - * physical device. + * physical device, if appropriate. */ mtd->dev.type = &mtd_devtype; mtd->dev.class = &mtd_class; @@ -532,6 +540,21 @@ static int mtd_add_device_partitions(struct mtd_info *mtd, return 0; } +/* + * Set a few defaults based on the parent devices, if not provided by the + * driver + */ +static void mtd_set_dev_defaults(struct mtd_info *mtd) +{ + if (mtd->dev.parent) { + if (!mtd->owner && mtd->dev.parent->driver) + mtd->owner = mtd->dev.parent->driver->owner; + if (!mtd->name) + mtd->name = dev_name(mtd->dev.parent); + } else { + pr_debug("mtd device won't show a device symlink in sysfs\n"); + } +} /** * mtd_device_parse_register - parse partitions and register an MTD device. @@ -570,6 +593,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, int ret; struct mtd_partition *real_parts = NULL; + mtd_set_dev_defaults(mtd); + ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data); if (ret <= 0 && nr_parts && parts) { real_parts = kmemdup(parts, sizeof(*parts) * nr_parts, @@ -579,9 +604,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. @@ -591,11 +624,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; } @@ -1188,8 +1224,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; @@ -1301,6 +1336,7 @@ static void __exit cleanup_mtd(void) remove_proc_entry("mtd", NULL); class_unregister(&mtd_class); bdi_destroy(&mtd_bdi); + idr_destroy(&mtd_idr); } module_init(init_mtd); |