mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-04 06:54:27 -05:00 
			
		
		
		
	These patches were finally accepted and are already present in the Linus's tree. This should be good enough to make is "backport" material. Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
		
			
				
	
	
		
			201 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 5b644aa012f67fd211138a067b9f351f30bdcc60 Mon Sep 17 00:00:00 2001
 | 
						|
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
 | 
						|
Date: Wed, 14 Mar 2018 13:10:42 +0100
 | 
						|
Subject: [PATCH] mtd: partitions: add of_match_table parser matching for the
 | 
						|
 "ofpart" type
 | 
						|
MIME-Version: 1.0
 | 
						|
Content-Type: text/plain; charset=UTF-8
 | 
						|
Content-Transfer-Encoding: 8bit
 | 
						|
 | 
						|
In order to properly support compatibility strings as described in the
 | 
						|
bindings/mtd/partition.txt "ofpart" type should be treated as an
 | 
						|
indication for looking into OF. MTD should check "compatible" property
 | 
						|
and search for a matching parser rather than blindly trying the one
 | 
						|
supporting "fixed-partitions".
 | 
						|
 | 
						|
It also means that existing "fixed-partitions" parser should get renamed
 | 
						|
to use a more meaningful name.
 | 
						|
 | 
						|
This commit achievies that aim by introducing a new mtd_part_of_parse().
 | 
						|
It works by looking for a matching parser for every string in the
 | 
						|
"compatibility" property (starting with the most specific one).
 | 
						|
 | 
						|
Please note that driver-specified parsers still take a precedence. It's
 | 
						|
assumed that driver providing a parser type has a good reason for that
 | 
						|
(e.g. having platform data with device-specific info). Also doing
 | 
						|
otherwise could break existing setups. The same applies to using default
 | 
						|
parsers (including "cmdlinepart") as some overwrite DT data with cmdline
 | 
						|
argument.
 | 
						|
 | 
						|
Partition parsers can now provide an of_match_table to enable
 | 
						|
flash<-->parser matching via device tree as documented in the
 | 
						|
mtd/partition.txt.
 | 
						|
 | 
						|
This support is currently limited to built-in parsers as it uses
 | 
						|
request_module() and friends. This should be sufficient for most cases
 | 
						|
though as compiling parsers as modules isn't a common choice.
 | 
						|
 | 
						|
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
 | 
						|
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
 | 
						|
Tested-by: Peter Rosin <peda@axentia.se>
 | 
						|
Reviewed-by: Richard Weinberger <richard@nod.at>
 | 
						|
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
 | 
						|
---
 | 
						|
 drivers/mtd/mtdpart.c          | 116 +++++++++++++++++++++++++++++++++++++----
 | 
						|
 include/linux/mtd/partitions.h |   1 +
 | 
						|
 2 files changed, 108 insertions(+), 9 deletions(-)
 | 
						|
 | 
						|
--- a/drivers/mtd/mtdpart.c
 | 
						|
+++ b/drivers/mtd/mtdpart.c
 | 
						|
@@ -30,6 +30,7 @@
 | 
						|
 #include <linux/mtd/mtd.h>
 | 
						|
 #include <linux/mtd/partitions.h>
 | 
						|
 #include <linux/err.h>
 | 
						|
+#include <linux/of.h>
 | 
						|
 
 | 
						|
 #include "mtdcore.h"
 | 
						|
 
 | 
						|
@@ -886,6 +887,92 @@ static int mtd_part_do_parse(struct mtd_
 | 
						|
 }
 | 
						|
 
 | 
						|
 /**
 | 
						|
+ * mtd_part_get_compatible_parser - find MTD parser by a compatible string
 | 
						|
+ *
 | 
						|
+ * @compat: compatible string describing partitions in a device tree
 | 
						|
+ *
 | 
						|
+ * MTD parsers can specify supported partitions by providing a table of
 | 
						|
+ * compatibility strings. This function finds a parser that advertises support
 | 
						|
+ * for a passed value of "compatible".
 | 
						|
+ */
 | 
						|
+static struct mtd_part_parser *mtd_part_get_compatible_parser(const char *compat)
 | 
						|
+{
 | 
						|
+	struct mtd_part_parser *p, *ret = NULL;
 | 
						|
+
 | 
						|
+	spin_lock(&part_parser_lock);
 | 
						|
+
 | 
						|
+	list_for_each_entry(p, &part_parsers, list) {
 | 
						|
+		const struct of_device_id *matches;
 | 
						|
+
 | 
						|
+		matches = p->of_match_table;
 | 
						|
+		if (!matches)
 | 
						|
+			continue;
 | 
						|
+
 | 
						|
+		for (; matches->compatible[0]; matches++) {
 | 
						|
+			if (!strcmp(matches->compatible, compat) &&
 | 
						|
+			    try_module_get(p->owner)) {
 | 
						|
+				ret = p;
 | 
						|
+				break;
 | 
						|
+			}
 | 
						|
+		}
 | 
						|
+
 | 
						|
+		if (ret)
 | 
						|
+			break;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	spin_unlock(&part_parser_lock);
 | 
						|
+
 | 
						|
+	return ret;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int mtd_part_of_parse(struct mtd_info *master,
 | 
						|
+			     struct mtd_partitions *pparts)
 | 
						|
+{
 | 
						|
+	struct mtd_part_parser *parser;
 | 
						|
+	struct device_node *np;
 | 
						|
+	struct property *prop;
 | 
						|
+	const char *compat;
 | 
						|
+	const char *fixed = "ofpart";
 | 
						|
+	int ret, err = 0;
 | 
						|
+
 | 
						|
+	np = of_get_child_by_name(mtd_get_of_node(master), "partitions");
 | 
						|
+	of_property_for_each_string(np, "compatible", prop, compat) {
 | 
						|
+		parser = mtd_part_get_compatible_parser(compat);
 | 
						|
+		if (!parser)
 | 
						|
+			continue;
 | 
						|
+		ret = mtd_part_do_parse(parser, master, pparts, NULL);
 | 
						|
+		if (ret > 0) {
 | 
						|
+			of_node_put(np);
 | 
						|
+			return ret;
 | 
						|
+		}
 | 
						|
+		mtd_part_parser_put(parser);
 | 
						|
+		if (ret < 0 && !err)
 | 
						|
+			err = ret;
 | 
						|
+	}
 | 
						|
+	of_node_put(np);
 | 
						|
+
 | 
						|
+	/*
 | 
						|
+	 * For backward compatibility we have to try the "ofpart"
 | 
						|
+	 * parser. It supports old DT format with partitions specified as a
 | 
						|
+	 * direct subnodes of a flash device DT node without any compatibility
 | 
						|
+	 * specified we could match.
 | 
						|
+	 */
 | 
						|
+	parser = mtd_part_parser_get(fixed);
 | 
						|
+	if (!parser && !request_module("%s", fixed))
 | 
						|
+		parser = mtd_part_parser_get(fixed);
 | 
						|
+	if (parser) {
 | 
						|
+		ret = mtd_part_do_parse(parser, master, pparts, NULL);
 | 
						|
+		if (ret > 0)
 | 
						|
+			return ret;
 | 
						|
+		mtd_part_parser_put(parser);
 | 
						|
+		if (ret < 0 && !err)
 | 
						|
+			err = ret;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return err;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/**
 | 
						|
  * parse_mtd_partitions - parse MTD partitions
 | 
						|
  * @master: the master partition (describes whole MTD device)
 | 
						|
  * @types: names of partition parsers to try or %NULL
 | 
						|
@@ -917,19 +1004,30 @@ int parse_mtd_partitions(struct mtd_info
 | 
						|
 		types = default_mtd_part_types;
 | 
						|
 
 | 
						|
 	for ( ; *types; types++) {
 | 
						|
-		pr_debug("%s: parsing partitions %s\n", master->name, *types);
 | 
						|
-		parser = mtd_part_parser_get(*types);
 | 
						|
-		if (!parser && !request_module("%s", *types))
 | 
						|
+		/*
 | 
						|
+		 * ofpart is a special type that means OF partitioning info
 | 
						|
+		 * should be used. It requires a bit different logic so it is
 | 
						|
+		 * handled in a separated function.
 | 
						|
+		 */
 | 
						|
+		if (!strcmp(*types, "ofpart")) {
 | 
						|
+			ret = mtd_part_of_parse(master, pparts);
 | 
						|
+		} else {
 | 
						|
+			pr_debug("%s: parsing partitions %s\n", master->name,
 | 
						|
+				 *types);
 | 
						|
 			parser = mtd_part_parser_get(*types);
 | 
						|
-		pr_debug("%s: got parser %s\n", master->name,
 | 
						|
-			 parser ? parser->name : NULL);
 | 
						|
-		if (!parser)
 | 
						|
-			continue;
 | 
						|
-		ret = mtd_part_do_parse(parser, master, pparts, data);
 | 
						|
+			if (!parser && !request_module("%s", *types))
 | 
						|
+				parser = mtd_part_parser_get(*types);
 | 
						|
+			pr_debug("%s: got parser %s\n", master->name,
 | 
						|
+				parser ? parser->name : NULL);
 | 
						|
+			if (!parser)
 | 
						|
+				continue;
 | 
						|
+			ret = mtd_part_do_parse(parser, master, pparts, data);
 | 
						|
+			if (ret <= 0)
 | 
						|
+				mtd_part_parser_put(parser);
 | 
						|
+		}
 | 
						|
 		/* Found partitions! */
 | 
						|
 		if (ret > 0)
 | 
						|
 			return 0;
 | 
						|
-		mtd_part_parser_put(parser);
 | 
						|
 		/*
 | 
						|
 		 * Stash the first error we see; only report it if no parser
 | 
						|
 		 * succeeds
 | 
						|
--- a/include/linux/mtd/partitions.h
 | 
						|
+++ b/include/linux/mtd/partitions.h
 | 
						|
@@ -77,6 +77,7 @@ struct mtd_part_parser {
 | 
						|
 	struct list_head list;
 | 
						|
 	struct module *owner;
 | 
						|
 	const char *name;
 | 
						|
+	const struct of_device_id *of_match_table;
 | 
						|
 	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);
 |