diff options
Diffstat (limited to 'drivers/mtd/mtdcore.c')
-rw-r--r-- | drivers/mtd/mtdcore.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 8bbbb751bf45..a91cee90aef9 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); @@ -418,6 +426,15 @@ int add_mtd_device(struct mtd_info *mtd) mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; + 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"); + } + /* Some chips always power up locked. Unlock them now */ if ((mtd->flags & MTD_WRITEABLE) && (mtd->flags & MTD_POWERUP_LOCK)) { error = mtd_unlock(mtd, 0, mtd->size); @@ -430,7 +447,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; @@ -579,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. @@ -591,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; } @@ -1301,6 +1329,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); |