aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafał Miłecki <rafal@milecki.pl>2018-03-14 08:10:42 -0400
committerBoris Brezillon <boris.brezillon@bootlin.com>2018-03-27 03:10:48 -0400
commit5b644aa012f67fd211138a067b9f351f30bdcc60 (patch)
tree59dc52a7c886e68fa6786df6936d95e1a9804721
parent5741a164ff6fb5abbea8548ad0f3846bad2b9aec (diff)
mtd: partitions: add of_match_table parser matching for the "ofpart" type
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>
-rw-r--r--drivers/mtd/mtdpart.c116
-rw-r--r--include/linux/mtd/partitions.h1
2 files changed, 108 insertions, 9 deletions
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 85fea8ea3423..2b7bb834ff40 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -30,6 +30,7 @@
30#include <linux/mtd/mtd.h> 30#include <linux/mtd/mtd.h>
31#include <linux/mtd/partitions.h> 31#include <linux/mtd/partitions.h>
32#include <linux/err.h> 32#include <linux/err.h>
33#include <linux/of.h>
33 34
34#include "mtdcore.h" 35#include "mtdcore.h"
35 36
@@ -846,6 +847,92 @@ static int mtd_part_do_parse(struct mtd_part_parser *parser,
846} 847}
847 848
848/** 849/**
850 * mtd_part_get_compatible_parser - find MTD parser by a compatible string
851 *
852 * @compat: compatible string describing partitions in a device tree
853 *
854 * MTD parsers can specify supported partitions by providing a table of
855 * compatibility strings. This function finds a parser that advertises support
856 * for a passed value of "compatible".
857 */
858static struct mtd_part_parser *mtd_part_get_compatible_parser(const char *compat)
859{
860 struct mtd_part_parser *p, *ret = NULL;
861
862 spin_lock(&part_parser_lock);
863
864 list_for_each_entry(p, &part_parsers, list) {
865 const struct of_device_id *matches;
866
867 matches = p->of_match_table;
868 if (!matches)
869 continue;
870
871 for (; matches->compatible[0]; matches++) {
872 if (!strcmp(matches->compatible, compat) &&
873 try_module_get(p->owner)) {
874 ret = p;
875 break;
876 }
877 }
878
879 if (ret)
880 break;
881 }
882
883 spin_unlock(&part_parser_lock);
884
885 return ret;
886}
887
888static int mtd_part_of_parse(struct mtd_info *master,
889 struct mtd_partitions *pparts)
890{
891 struct mtd_part_parser *parser;
892 struct device_node *np;
893 struct property *prop;
894 const char *compat;
895 const char *fixed = "ofpart";
896 int ret, err = 0;
897
898 np = of_get_child_by_name(mtd_get_of_node(master), "partitions");
899 of_property_for_each_string(np, "compatible", prop, compat) {
900 parser = mtd_part_get_compatible_parser(compat);
901 if (!parser)
902 continue;
903 ret = mtd_part_do_parse(parser, master, pparts, NULL);
904 if (ret > 0) {
905 of_node_put(np);
906 return ret;
907 }
908 mtd_part_parser_put(parser);
909 if (ret < 0 && !err)
910 err = ret;
911 }
912 of_node_put(np);
913
914 /*
915 * For backward compatibility we have to try the "ofpart"
916 * parser. It supports old DT format with partitions specified as a
917 * direct subnodes of a flash device DT node without any compatibility
918 * specified we could match.
919 */
920 parser = mtd_part_parser_get(fixed);
921 if (!parser && !request_module("%s", fixed))
922 parser = mtd_part_parser_get(fixed);
923 if (parser) {
924 ret = mtd_part_do_parse(parser, master, pparts, NULL);
925 if (ret > 0)
926 return ret;
927 mtd_part_parser_put(parser);
928 if (ret < 0 && !err)
929 err = ret;
930 }
931
932 return err;
933}
934
935/**
849 * parse_mtd_partitions - parse MTD partitions 936 * parse_mtd_partitions - parse MTD partitions
850 * @master: the master partition (describes whole MTD device) 937 * @master: the master partition (describes whole MTD device)
851 * @types: names of partition parsers to try or %NULL 938 * @types: names of partition parsers to try or %NULL
@@ -877,19 +964,30 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
877 types = default_mtd_part_types; 964 types = default_mtd_part_types;
878 965
879 for ( ; *types; types++) { 966 for ( ; *types; types++) {
880 pr_debug("%s: parsing partitions %s\n", master->name, *types); 967 /*
881 parser = mtd_part_parser_get(*types); 968 * ofpart is a special type that means OF partitioning info
882 if (!parser && !request_module("%s", *types)) 969 * should be used. It requires a bit different logic so it is
970 * handled in a separated function.
971 */
972 if (!strcmp(*types, "ofpart")) {
973 ret = mtd_part_of_parse(master, pparts);
974 } else {
975 pr_debug("%s: parsing partitions %s\n", master->name,
976 *types);
883 parser = mtd_part_parser_get(*types); 977 parser = mtd_part_parser_get(*types);
884 pr_debug("%s: got parser %s\n", master->name, 978 if (!parser && !request_module("%s", *types))
885 parser ? parser->name : NULL); 979 parser = mtd_part_parser_get(*types);
886 if (!parser) 980 pr_debug("%s: got parser %s\n", master->name,
887 continue; 981 parser ? parser->name : NULL);
888 ret = mtd_part_do_parse(parser, master, pparts, data); 982 if (!parser)
983 continue;
984 ret = mtd_part_do_parse(parser, master, pparts, data);
985 if (ret <= 0)
986 mtd_part_parser_put(parser);
987 }
889 /* Found partitions! */ 988 /* Found partitions! */
890 if (ret > 0) 989 if (ret > 0)
891 return 0; 990 return 0;
892 mtd_part_parser_put(parser);
893 /* 991 /*
894 * Stash the first error we see; only report it if no parser 992 * Stash the first error we see; only report it if no parser
895 * succeeds 993 * succeeds
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index c4beb70dacbd..11cb0c50cd84 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -77,6 +77,7 @@ struct mtd_part_parser {
77 struct list_head list; 77 struct list_head list;
78 struct module *owner; 78 struct module *owner;
79 const char *name; 79 const char *name;
80 const struct of_device_id *of_match_table;
80 int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, 81 int (*parse_fn)(struct mtd_info *, const struct mtd_partition **,
81 struct mtd_part_parser_data *); 82 struct mtd_part_parser_data *);
82 void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); 83 void (*cleanup)(const struct mtd_partition *pparts, int nr_parts);