From: Gabor Juhos Subject: mtd: add support for different partition parser types Signed-off-by: Gabor Juhos --- drivers/mtd/mtdpart.c | 56 ++++++++++++++++++++++++++++++++++++++++ include/linux/mtd/partitions.h | 11 ++++++++ 2 files changed, 67 insertions(+) --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -55,6 +55,10 @@ struct mtd_part { }; static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part); +static int parse_mtd_partitions_by_type(struct mtd_info *master, + enum mtd_parser_type type, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data); /* * Given a pointer to the MTD object in the mtd_part structure, we can retrieve @@ -717,6 +721,36 @@ int mtd_del_partition(struct mtd_info *m } EXPORT_SYMBOL_GPL(mtd_del_partition); +static int +run_parsers_by_type(struct mtd_part *slave, enum mtd_parser_type type) +{ + struct mtd_partition *parts; + int nr_parts; + int i; + + nr_parts = parse_mtd_partitions_by_type(&slave->mtd, type, (const struct mtd_partition **)&parts, + NULL); + if (nr_parts <= 0) + return nr_parts; + + if (WARN_ON(!parts)) + return 0; + + for (i = 0; i < nr_parts; i++) { + /* adjust partition offsets */ + parts[i].offset += slave->offset; + + mtd_add_partition(slave->parent, + parts[i].name, + parts[i].offset, + parts[i].size); + } + + kfree(parts); + + return nr_parts; +} + #ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME #define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME #else @@ -1066,6 +1100,61 @@ void mtd_part_parser_cleanup(struct mtd_ } } +static struct mtd_part_parser * +get_partition_parser_by_type(enum mtd_parser_type type, + struct mtd_part_parser *start) +{ + struct mtd_part_parser *p, *ret = NULL; + + spin_lock(&part_parser_lock); + + p = list_prepare_entry(start, &part_parsers, list); + if (start) + mtd_part_parser_put(start); + + list_for_each_entry_continue(p, &part_parsers, list) { + if (p->type == type && try_module_get(p->owner)) { + ret = p; + break; + } + } + + spin_unlock(&part_parser_lock); + + return ret; +} + +static int parse_mtd_partitions_by_type(struct mtd_info *master, + enum mtd_parser_type type, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +{ + struct mtd_part_parser *prev = NULL; + int ret = 0; + + while (1) { + struct mtd_part_parser *parser; + + parser = get_partition_parser_by_type(type, prev); + if (!parser) + break; + + ret = (*parser->parse_fn)(master, pparts, data); + + if (ret > 0) { + mtd_part_parser_put(parser); + printk(KERN_NOTICE + "%d %s partitions found on MTD device %s\n", + ret, parser->name, master->name); + break; + } + + prev = parser; + } + + return ret; +} + int mtd_is_partition(const struct mtd_info *mtd) { struct mtd_part *part; --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h @@ -73,6 +73,10 @@ struct mtd_part_parser_data { * Functions dealing with the various ways of partitioning the space */ +enum mtd_parser_type { + MTD_PARSER_TYPE_DEVICE = 0, +}; + struct mtd_part_parser { struct list_head list; struct module *owner; @@ -81,6 +85,7 @@ struct mtd_part_parser { int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, struct mtd_part_parser_data *); void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); + enum mtd_parser_type type; }; /* Container for passing around a set of parsed partitions */