From 02cff0ccaa6d364f5c1eeea83f47ac80ccc967d4 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Tue, 3 Sep 2013 18:11:50 +0200
Subject: [PATCH] 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
@@ -740,6 +740,30 @@ static struct mtd_part_parser *get_parti
 
 #define put_partition_parser(p) do { module_put((p)->owner); } while (0)
 
+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)
+		put_partition_parser(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;
+}
+
 void register_mtd_parser(struct mtd_part_parser *p)
 {
 	spin_lock(&part_parser_lock);
@@ -868,6 +892,38 @@ int parse_mtd_partitions(struct mtd_info
 	return err;
 }
 
+int parse_mtd_partitions_by_type(struct mtd_info *master,
+				 enum mtd_parser_type type,
+				 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) {
+			put_partition_parser(parser);
+			printk(KERN_NOTICE
+			       "%d %s partitions found on MTD device %s\n",
+			       ret, parser->name, master->name);
+			break;
+		}
+
+		prev = parser;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(parse_mtd_partitions_by_type);
+
 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
@@ -68,12 +68,17 @@ 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;
 	const char *name;
 	int (*parse_fn)(struct mtd_info *, struct mtd_partition **,
 			struct mtd_part_parser_data *);
+	enum mtd_parser_type type;
 };
 
 extern void register_mtd_parser(struct mtd_part_parser *parser);
@@ -87,4 +92,9 @@ uint64_t mtd_get_device_size(const struc
 extern void __weak arch_split_mtd_part(struct mtd_info *master,
 				       const char *name, int offset, int size);
 
+int parse_mtd_partitions_by_type(struct mtd_info *master,
+				 enum mtd_parser_type type,
+				 struct mtd_partition **pparts,
+				 struct mtd_part_parser_data *data);
+
 #endif
