mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 05:54:26 -04: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"
 | |
|  
 | |
| @@ -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);
 |