diff options
author | Michal Suchanek <hramrach@gmail.com> | 2015-08-18 18:34:09 +0300 |
---|---|---|
committer | Brian Norris <computersforpeace@gmail.com> | 2015-10-31 00:01:39 +0300 |
commit | 5cfdedb7b9a0fe38aa4838bfe66fb9ebc2c9ce15 (patch) | |
tree | f9b6b8f882819bd02ed3df06baa4caea8222180e /drivers/mtd | |
parent | fe2585e9c29a650af26824684e5033757fd6bc0c (diff) | |
download | linux-5cfdedb7b9a0fe38aa4838bfe66fb9ebc2c9ce15.tar.xz |
mtd: ofpart: move ofpart partitions to a dedicated dt node
Parsing direct subnodes of a mtd device as partitions is unreliable
since the mtd device is also part of its bus subsystem and can contain
bus data in subnodes.
Move ofpart data to a subnode of its own so it is clear which data is
part of the partition layout.
Signed-off-by: Michal Suchanek <hramrach@gmail.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/ofpart.c | 63 |
1 files changed, 46 insertions, 17 deletions
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index aa26c32e1bc2..669c3452f278 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -29,23 +29,33 @@ static int parse_ofpart_partitions(struct mtd_info *master, struct mtd_partition **pparts, struct mtd_part_parser_data *data) { - struct device_node *node; + struct device_node *mtd_node; + struct device_node *ofpart_node; const char *partname; struct device_node *pp; - int nr_parts, i; + int nr_parts, i, ret = 0; + bool dedicated = true; if (!data) return 0; - node = data->of_node; - if (!node) + mtd_node = data->of_node; + if (!mtd_node) return 0; + ofpart_node = of_get_child_by_name(mtd_node, "partitions"); + if (!ofpart_node) { + pr_warn("%s: 'partitions' subnode not found on %s. Trying to parse direct subnodes as partitions.\n", + master->name, mtd_node->full_name); + ofpart_node = mtd_node; + dedicated = false; + } + /* First count the subnodes */ nr_parts = 0; - for_each_child_of_node(node, pp) { - if (node_has_compatible(pp)) + for_each_child_of_node(ofpart_node, pp) { + if (!dedicated && node_has_compatible(pp)) continue; nr_parts++; @@ -59,22 +69,36 @@ static int parse_ofpart_partitions(struct mtd_info *master, return -ENOMEM; i = 0; - for_each_child_of_node(node, pp) { + for_each_child_of_node(ofpart_node, pp) { const __be32 *reg; int len; int a_cells, s_cells; - if (node_has_compatible(pp)) + if (!dedicated && node_has_compatible(pp)) continue; reg = of_get_property(pp, "reg", &len); if (!reg) { - nr_parts--; - continue; + if (dedicated) { + pr_debug("%s: ofpart partition %s (%s) missing reg property.\n", + master->name, pp->full_name, + mtd_node->full_name); + goto ofpart_fail; + } else { + nr_parts--; + continue; + } } a_cells = of_n_addr_cells(pp); s_cells = of_n_size_cells(pp); + if (len / 4 != a_cells + s_cells) { + pr_debug("%s: ofpart partition %s (%s) error parsing reg property.\n", + master->name, pp->full_name, + mtd_node->full_name); + goto ofpart_fail; + } + (*pparts)[i].offset = of_read_number(reg, a_cells); (*pparts)[i].size = of_read_number(reg + a_cells, s_cells); @@ -92,15 +116,20 @@ static int parse_ofpart_partitions(struct mtd_info *master, i++; } - if (!i) { - of_node_put(pp); - pr_err("No valid partition found on %s\n", node->full_name); - kfree(*pparts); - *pparts = NULL; - return -EINVAL; - } + if (!nr_parts) + goto ofpart_none; return nr_parts; + +ofpart_fail: + pr_err("%s: error parsing ofpart partition %s (%s)\n", + master->name, pp->full_name, mtd_node->full_name); + ret = -EINVAL; +ofpart_none: + of_node_put(pp); + kfree(*pparts); + *pparts = NULL; + return ret; } static struct mtd_part_parser ofpart_parser = { |