160-0001-mtd-partitions-add-of_match_table-parser-matching-fo.patch 6.0 KB

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