These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / mtd / ofpart.c
index aa26c32..9ed6038 100644 (file)
@@ -29,23 +29,41 @@ 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) {
+               /*
+                * We might get here even when ofpart isn't used at all (e.g.,
+                * when using another parser), so don't be louder than
+                * KERN_DEBUG
+                */
+               pr_debug("%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;
+       } else if (!of_device_is_compatible(ofpart_node, "fixed-partitions")) {
+               /* The 'partitions' subnode might be used by another parser */
+               return 0;
+       }
+
        /* 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 +77,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 +124,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 = {