mtd: ofpart: move ofpart partitions to a dedicated dt node
authorMichal Suchanek <hramrach@gmail.com>
Tue, 18 Aug 2015 15:34:09 +0000 (15:34 +0000)
committerBrian Norris <computersforpeace@gmail.com>
Fri, 30 Oct 2015 21:01:39 +0000 (14:01 -0700)
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>
drivers/mtd/ofpart.c

index aa26c32e1bc28943426992eba09fddc207cf104d..669c3452f278fb0e365570872893855c9ce21e2c 100644 (file)
@@ -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 = {