diff options
| -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, | |||
| 29 | struct mtd_partition **pparts, | 29 | struct mtd_partition **pparts, |
| 30 | struct mtd_part_parser_data *data) | 30 | struct mtd_part_parser_data *data) |
| 31 | { | 31 | { |
| 32 | struct device_node *node; | 32 | struct device_node *mtd_node; |
| 33 | struct device_node *ofpart_node; | ||
| 33 | const char *partname; | 34 | const char *partname; |
| 34 | struct device_node *pp; | 35 | struct device_node *pp; |
| 35 | int nr_parts, i; | 36 | int nr_parts, i, ret = 0; |
| 37 | bool dedicated = true; | ||
| 36 | 38 | ||
| 37 | 39 | ||
| 38 | if (!data) | 40 | if (!data) |
| 39 | return 0; | 41 | return 0; |
| 40 | 42 | ||
| 41 | node = data->of_node; | 43 | mtd_node = data->of_node; |
| 42 | if (!node) | 44 | if (!mtd_node) |
| 43 | return 0; | 45 | return 0; |
| 44 | 46 | ||
| 47 | ofpart_node = of_get_child_by_name(mtd_node, "partitions"); | ||
| 48 | if (!ofpart_node) { | ||
| 49 | pr_warn("%s: 'partitions' subnode not found on %s. Trying to parse direct subnodes as partitions.\n", | ||
| 50 | master->name, mtd_node->full_name); | ||
| 51 | ofpart_node = mtd_node; | ||
| 52 | dedicated = false; | ||
| 53 | } | ||
| 54 | |||
| 45 | /* First count the subnodes */ | 55 | /* First count the subnodes */ |
| 46 | nr_parts = 0; | 56 | nr_parts = 0; |
| 47 | for_each_child_of_node(node, pp) { | 57 | for_each_child_of_node(ofpart_node, pp) { |
| 48 | if (node_has_compatible(pp)) | 58 | if (!dedicated && node_has_compatible(pp)) |
| 49 | continue; | 59 | continue; |
| 50 | 60 | ||
| 51 | nr_parts++; | 61 | nr_parts++; |
| @@ -59,22 +69,36 @@ static int parse_ofpart_partitions(struct mtd_info *master, | |||
| 59 | return -ENOMEM; | 69 | return -ENOMEM; |
| 60 | 70 | ||
| 61 | i = 0; | 71 | i = 0; |
| 62 | for_each_child_of_node(node, pp) { | 72 | for_each_child_of_node(ofpart_node, pp) { |
| 63 | const __be32 *reg; | 73 | const __be32 *reg; |
| 64 | int len; | 74 | int len; |
| 65 | int a_cells, s_cells; | 75 | int a_cells, s_cells; |
| 66 | 76 | ||
| 67 | if (node_has_compatible(pp)) | 77 | if (!dedicated && node_has_compatible(pp)) |
| 68 | continue; | 78 | continue; |
| 69 | 79 | ||
| 70 | reg = of_get_property(pp, "reg", &len); | 80 | reg = of_get_property(pp, "reg", &len); |
| 71 | if (!reg) { | 81 | if (!reg) { |
| 72 | nr_parts--; | 82 | if (dedicated) { |
| 73 | continue; | 83 | pr_debug("%s: ofpart partition %s (%s) missing reg property.\n", |
| 84 | master->name, pp->full_name, | ||
| 85 | mtd_node->full_name); | ||
| 86 | goto ofpart_fail; | ||
| 87 | } else { | ||
| 88 | nr_parts--; | ||
| 89 | continue; | ||
| 90 | } | ||
| 74 | } | 91 | } |
| 75 | 92 | ||
| 76 | a_cells = of_n_addr_cells(pp); | 93 | a_cells = of_n_addr_cells(pp); |
| 77 | s_cells = of_n_size_cells(pp); | 94 | s_cells = of_n_size_cells(pp); |
| 95 | if (len / 4 != a_cells + s_cells) { | ||
| 96 | pr_debug("%s: ofpart partition %s (%s) error parsing reg property.\n", | ||
| 97 | master->name, pp->full_name, | ||
| 98 | mtd_node->full_name); | ||
| 99 | goto ofpart_fail; | ||
| 100 | } | ||
| 101 | |||
| 78 | (*pparts)[i].offset = of_read_number(reg, a_cells); | 102 | (*pparts)[i].offset = of_read_number(reg, a_cells); |
| 79 | (*pparts)[i].size = of_read_number(reg + a_cells, s_cells); | 103 | (*pparts)[i].size = of_read_number(reg + a_cells, s_cells); |
| 80 | 104 | ||
| @@ -92,15 +116,20 @@ static int parse_ofpart_partitions(struct mtd_info *master, | |||
| 92 | i++; | 116 | i++; |
| 93 | } | 117 | } |
| 94 | 118 | ||
| 95 | if (!i) { | 119 | if (!nr_parts) |
| 96 | of_node_put(pp); | 120 | goto ofpart_none; |
| 97 | pr_err("No valid partition found on %s\n", node->full_name); | ||
| 98 | kfree(*pparts); | ||
| 99 | *pparts = NULL; | ||
| 100 | return -EINVAL; | ||
| 101 | } | ||
| 102 | 121 | ||
| 103 | return nr_parts; | 122 | return nr_parts; |
| 123 | |||
| 124 | ofpart_fail: | ||
| 125 | pr_err("%s: error parsing ofpart partition %s (%s)\n", | ||
| 126 | master->name, pp->full_name, mtd_node->full_name); | ||
| 127 | ret = -EINVAL; | ||
| 128 | ofpart_none: | ||
| 129 | of_node_put(pp); | ||
| 130 | kfree(*pparts); | ||
| 131 | *pparts = NULL; | ||
| 132 | return ret; | ||
| 104 | } | 133 | } |
| 105 | 134 | ||
| 106 | static struct mtd_part_parser ofpart_parser = { | 135 | static struct mtd_part_parser ofpart_parser = { |
