| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 | 
							- From 5b644aa012f67fd211138a067b9f351f30bdcc60 Mon Sep 17 00:00:00 2001
 
- From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
 
- 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 <[email protected]>
 
- Signed-off-by: Rafał Miłecki <[email protected]>
 
- Tested-by: Peter Rosin <[email protected]>
 
- Reviewed-by: Richard Weinberger <[email protected]>
 
- Signed-off-by: Boris Brezillon <[email protected]>
 
- ---
 
-  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"
 
-  
 
- @@ -894,6 +895,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
 
- @@ -925,19 +1012,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);
 
 
  |