/branches/18.06.1/target/linux/generic/backport-4.9/067-v4.17-0001-mtd-partitions-add-of_match_table-parser-matching-fo.patch |
@@ -0,0 +1,200 @@ |
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); |