diff options
Diffstat (limited to 'drivers/mtd/mtdcore.c')
-rw-r--r-- | drivers/mtd/mtdcore.c | 40 |
1 files changed, 23 insertions, 17 deletions
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index ffa288474820..309625130b21 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -32,6 +32,7 @@ #include <linux/err.h> #include <linux/ioctl.h> #include <linux/init.h> +#include <linux/of.h> #include <linux/proc_fs.h> #include <linux/idr.h> #include <linux/backing-dev.h> @@ -445,6 +446,7 @@ int add_mtd_device(struct mtd_info *mtd) mtd->dev.devt = MTD_DEVT(i); dev_set_name(&mtd->dev, "mtd%d", i); dev_set_drvdata(&mtd->dev, mtd); + of_node_get(mtd_get_of_node(mtd)); error = device_register(&mtd->dev); if (error) goto fail_added; @@ -467,6 +469,7 @@ int add_mtd_device(struct mtd_info *mtd) return 0; fail_added: + of_node_put(mtd_get_of_node(mtd)); idr_remove(&mtd_idr, i); fail_locked: mutex_unlock(&mtd_table_mutex); @@ -508,6 +511,7 @@ int del_mtd_device(struct mtd_info *mtd) device_unregister(&mtd->dev); idr_remove(&mtd_idr, mtd->index); + of_node_put(mtd_get_of_node(mtd)); module_put(THIS_MODULE); ret = 0; @@ -519,9 +523,10 @@ out_error: } static int mtd_add_device_partitions(struct mtd_info *mtd, - struct mtd_partition *real_parts, - int nbparts) + struct mtd_partitions *parts) { + const struct mtd_partition *real_parts = parts->parts; + int nbparts = parts->nr_parts; int ret; if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) { @@ -590,29 +595,29 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, const struct mtd_partition *parts, int nr_parts) { + struct mtd_partitions parsed; 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, - GFP_KERNEL); - if (!real_parts) - ret = -ENOMEM; - else - ret = nr_parts; - } - /* Didn't come up with either parsed OR fallback partitions */ - if (ret < 0) { + memset(&parsed, 0, sizeof(parsed)); + + ret = parse_mtd_partitions(mtd, types, &parsed, parser_data); + if ((ret < 0 || parsed.nr_parts == 0) && parts && nr_parts) { + /* Fall back to driver-provided partitions */ + parsed = (struct mtd_partitions){ + .parts = parts, + .nr_parts = nr_parts, + }; + } else if (ret < 0) { + /* Didn't come up with parsed OR fallback partitions */ 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; + memset(&parsed, 0, sizeof(parsed)); } - ret = mtd_add_device_partitions(mtd, real_parts, ret); + ret = mtd_add_device_partitions(mtd, &parsed); if (ret) goto out; @@ -632,7 +637,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, } out: - kfree(real_parts); + /* Cleanup any parsed partitions */ + mtd_part_parser_cleanup(&parsed); return ret; } EXPORT_SYMBOL_GPL(mtd_device_parse_register); |