OpenWrt – Rev 1

Subversion Repositories:
Rev:
From: Gabor Juhos <juhosg@openwrt.org>
Subject: mtd: add support for different partition parser types

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 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
@@ -56,6 +56,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
@@ -751,6 +755,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
@@ -1122,6 +1156,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 */