OpenWrt – Blame information for rev 2
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From 5b644aa012f67fd211138a067b9f351f30bdcc60 Mon Sep 17 00:00:00 2001 |
2 | From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl> |
||
3 | Date: Wed, 14 Mar 2018 13:10:42 +0100 |
||
4 | Subject: [PATCH] mtd: partitions: add of_match_table parser matching for the |
||
5 | "ofpart" type |
||
6 | MIME-Version: 1.0 |
||
7 | Content-Type: text/plain; charset=UTF-8 |
||
8 | Content-Transfer-Encoding: 8bit |
||
9 | |||
10 | In order to properly support compatibility strings as described in the |
||
11 | bindings/mtd/partition.txt "ofpart" type should be treated as an |
||
12 | indication for looking into OF. MTD should check "compatible" property |
||
13 | and search for a matching parser rather than blindly trying the one |
||
14 | supporting "fixed-partitions". |
||
15 | |||
16 | It also means that existing "fixed-partitions" parser should get renamed |
||
17 | to use a more meaningful name. |
||
18 | |||
19 | This commit achievies that aim by introducing a new mtd_part_of_parse(). |
||
20 | It works by looking for a matching parser for every string in the |
||
21 | "compatibility" property (starting with the most specific one). |
||
22 | |||
23 | Please note that driver-specified parsers still take a precedence. It's |
||
24 | assumed that driver providing a parser type has a good reason for that |
||
25 | (e.g. having platform data with device-specific info). Also doing |
||
26 | otherwise could break existing setups. The same applies to using default |
||
27 | parsers (including "cmdlinepart") as some overwrite DT data with cmdline |
||
28 | argument. |
||
29 | |||
30 | Partition parsers can now provide an of_match_table to enable |
||
31 | flash<-->parser matching via device tree as documented in the |
||
32 | mtd/partition.txt. |
||
33 | |||
34 | This support is currently limited to built-in parsers as it uses |
||
35 | request_module() and friends. This should be sufficient for most cases |
||
36 | though as compiling parsers as modules isn't a common choice. |
||
37 | |||
38 | Signed-off-by: Brian Norris <computersforpeace@gmail.com> |
||
39 | Signed-off-by: Rafał Miłecki <rafal@milecki.pl> |
||
40 | Tested-by: Peter Rosin <peda@axentia.se> |
||
41 | Reviewed-by: Richard Weinberger <richard@nod.at> |
||
42 | Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com> |
||
43 | --- |
||
44 | drivers/mtd/mtdpart.c | 116 +++++++++++++++++++++++++++++++++++++---- |
||
45 | include/linux/mtd/partitions.h | 1 + |
||
46 | 2 files changed, 108 insertions(+), 9 deletions(-) |
||
47 | |||
48 | --- a/drivers/mtd/mtdpart.c |
||
49 | +++ b/drivers/mtd/mtdpart.c |
||
50 | @@ -30,6 +30,7 @@ |
||
51 | #include <linux/mtd/mtd.h> |
||
52 | #include <linux/mtd/partitions.h> |
||
53 | #include <linux/err.h> |
||
54 | +#include <linux/of.h> |
||
55 | |||
56 | #include "mtdcore.h" |
||
57 | |||
58 | @@ -886,6 +887,92 @@ static int mtd_part_do_parse(struct mtd_ |
||
59 | } |
||
60 | |||
61 | /** |
||
62 | + * mtd_part_get_compatible_parser - find MTD parser by a compatible string |
||
63 | + * |
||
64 | + * @compat: compatible string describing partitions in a device tree |
||
65 | + * |
||
66 | + * MTD parsers can specify supported partitions by providing a table of |
||
67 | + * compatibility strings. This function finds a parser that advertises support |
||
68 | + * for a passed value of "compatible". |
||
69 | + */ |
||
70 | +static struct mtd_part_parser *mtd_part_get_compatible_parser(const char *compat) |
||
71 | +{ |
||
72 | + struct mtd_part_parser *p, *ret = NULL; |
||
73 | + |
||
74 | + spin_lock(&part_parser_lock); |
||
75 | + |
||
76 | + list_for_each_entry(p, &part_parsers, list) { |
||
77 | + const struct of_device_id *matches; |
||
78 | + |
||
79 | + matches = p->of_match_table; |
||
80 | + if (!matches) |
||
81 | + continue; |
||
82 | + |
||
83 | + for (; matches->compatible[0]; matches++) { |
||
84 | + if (!strcmp(matches->compatible, compat) && |
||
85 | + try_module_get(p->owner)) { |
||
86 | + ret = p; |
||
87 | + break; |
||
88 | + } |
||
89 | + } |
||
90 | + |
||
91 | + if (ret) |
||
92 | + break; |
||
93 | + } |
||
94 | + |
||
95 | + spin_unlock(&part_parser_lock); |
||
96 | + |
||
97 | + return ret; |
||
98 | +} |
||
99 | + |
||
100 | +static int mtd_part_of_parse(struct mtd_info *master, |
||
101 | + struct mtd_partitions *pparts) |
||
102 | +{ |
||
103 | + struct mtd_part_parser *parser; |
||
104 | + struct device_node *np; |
||
105 | + struct property *prop; |
||
106 | + const char *compat; |
||
107 | + const char *fixed = "ofpart"; |
||
108 | + int ret, err = 0; |
||
109 | + |
||
110 | + np = of_get_child_by_name(mtd_get_of_node(master), "partitions"); |
||
111 | + of_property_for_each_string(np, "compatible", prop, compat) { |
||
112 | + parser = mtd_part_get_compatible_parser(compat); |
||
113 | + if (!parser) |
||
114 | + continue; |
||
115 | + ret = mtd_part_do_parse(parser, master, pparts, NULL); |
||
116 | + if (ret > 0) { |
||
117 | + of_node_put(np); |
||
118 | + return ret; |
||
119 | + } |
||
120 | + mtd_part_parser_put(parser); |
||
121 | + if (ret < 0 && !err) |
||
122 | + err = ret; |
||
123 | + } |
||
124 | + of_node_put(np); |
||
125 | + |
||
126 | + /* |
||
127 | + * For backward compatibility we have to try the "ofpart" |
||
128 | + * parser. It supports old DT format with partitions specified as a |
||
129 | + * direct subnodes of a flash device DT node without any compatibility |
||
130 | + * specified we could match. |
||
131 | + */ |
||
132 | + parser = mtd_part_parser_get(fixed); |
||
133 | + if (!parser && !request_module("%s", fixed)) |
||
134 | + parser = mtd_part_parser_get(fixed); |
||
135 | + if (parser) { |
||
136 | + ret = mtd_part_do_parse(parser, master, pparts, NULL); |
||
137 | + if (ret > 0) |
||
138 | + return ret; |
||
139 | + mtd_part_parser_put(parser); |
||
140 | + if (ret < 0 && !err) |
||
141 | + err = ret; |
||
142 | + } |
||
143 | + |
||
144 | + return err; |
||
145 | +} |
||
146 | + |
||
147 | +/** |
||
148 | * parse_mtd_partitions - parse MTD partitions |
||
149 | * @master: the master partition (describes whole MTD device) |
||
150 | * @types: names of partition parsers to try or %NULL |
||
151 | @@ -917,19 +1004,30 @@ int parse_mtd_partitions(struct mtd_info |
||
152 | types = default_mtd_part_types; |
||
153 | |||
154 | for ( ; *types; types++) { |
||
155 | - pr_debug("%s: parsing partitions %s\n", master->name, *types); |
||
156 | - parser = mtd_part_parser_get(*types); |
||
157 | - if (!parser && !request_module("%s", *types)) |
||
158 | + /* |
||
159 | + * ofpart is a special type that means OF partitioning info |
||
160 | + * should be used. It requires a bit different logic so it is |
||
161 | + * handled in a separated function. |
||
162 | + */ |
||
163 | + if (!strcmp(*types, "ofpart")) { |
||
164 | + ret = mtd_part_of_parse(master, pparts); |
||
165 | + } else { |
||
166 | + pr_debug("%s: parsing partitions %s\n", master->name, |
||
167 | + *types); |
||
168 | parser = mtd_part_parser_get(*types); |
||
169 | - pr_debug("%s: got parser %s\n", master->name, |
||
170 | - parser ? parser->name : NULL); |
||
171 | - if (!parser) |
||
172 | - continue; |
||
173 | - ret = mtd_part_do_parse(parser, master, pparts, data); |
||
174 | + if (!parser && !request_module("%s", *types)) |
||
175 | + parser = mtd_part_parser_get(*types); |
||
176 | + pr_debug("%s: got parser %s\n", master->name, |
||
177 | + parser ? parser->name : NULL); |
||
178 | + if (!parser) |
||
179 | + continue; |
||
180 | + ret = mtd_part_do_parse(parser, master, pparts, data); |
||
181 | + if (ret <= 0) |
||
182 | + mtd_part_parser_put(parser); |
||
183 | + } |
||
184 | /* Found partitions! */ |
||
185 | if (ret > 0) |
||
186 | return 0; |
||
187 | - mtd_part_parser_put(parser); |
||
188 | /* |
||
189 | * Stash the first error we see; only report it if no parser |
||
190 | * succeeds |
||
191 | --- a/include/linux/mtd/partitions.h |
||
192 | +++ b/include/linux/mtd/partitions.h |
||
193 | @@ -77,6 +77,7 @@ struct mtd_part_parser { |
||
194 | struct list_head list; |
||
195 | struct module *owner; |
||
196 | const char *name; |
||
197 | + const struct of_device_id *of_match_table; |
||
198 | int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, |
||
199 | struct mtd_part_parser_data *); |
||
200 | void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); |