diff options
Diffstat (limited to 'drivers/mtd/mtdconcat.c')
-rw-r--r-- | drivers/mtd/mtdconcat.c | 51 |
1 files changed, 35 insertions, 16 deletions
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 3c8d5e6fa010..1fea631b5852 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c | |||
@@ -56,7 +56,7 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
56 | size_t * retlen, u_char * buf) | 56 | size_t * retlen, u_char * buf) |
57 | { | 57 | { |
58 | struct mtd_concat *concat = CONCAT(mtd); | 58 | struct mtd_concat *concat = CONCAT(mtd); |
59 | int ret = 0, err = -EINVAL; | 59 | int ret = 0, err; |
60 | int i; | 60 | int i; |
61 | 61 | ||
62 | *retlen = 0; | 62 | *retlen = 0; |
@@ -80,28 +80,29 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
80 | 80 | ||
81 | err = subdev->read(subdev, from, size, &retsize, buf); | 81 | err = subdev->read(subdev, from, size, &retsize, buf); |
82 | 82 | ||
83 | if (err && (err != -EBADMSG) && (err != -EUCLEAN)) | ||
84 | break; | ||
85 | |||
86 | /* Save information about bitflips! */ | 83 | /* Save information about bitflips! */ |
87 | if (err) { | 84 | if (unlikely(err)) { |
88 | if (err == -EBADMSG) | 85 | if (err == -EBADMSG) { |
89 | ret = err; | 86 | mtd->ecc_stats.failed++; |
90 | else if (!ret) | ||
91 | ret = err; | 87 | ret = err; |
92 | err = 0; | 88 | } else if (err == -EUCLEAN) { |
89 | mtd->ecc_stats.corrected++; | ||
90 | /* Do not overwrite -EBADMSG !! */ | ||
91 | if (!ret) | ||
92 | ret = err; | ||
93 | } else | ||
94 | return err; | ||
93 | } | 95 | } |
94 | 96 | ||
95 | *retlen += retsize; | 97 | *retlen += retsize; |
96 | len -= size; | 98 | len -= size; |
97 | if (len == 0) | 99 | if (len == 0) |
98 | break; | 100 | return ret; |
99 | 101 | ||
100 | err = -EINVAL; | ||
101 | buf += size; | 102 | buf += size; |
102 | from = 0; | 103 | from = 0; |
103 | } | 104 | } |
104 | return err ? err : ret; | 105 | return -EINVAL; |
105 | } | 106 | } |
106 | 107 | ||
107 | static int | 108 | static int |
@@ -244,7 +245,7 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) | |||
244 | { | 245 | { |
245 | struct mtd_concat *concat = CONCAT(mtd); | 246 | struct mtd_concat *concat = CONCAT(mtd); |
246 | struct mtd_oob_ops devops = *ops; | 247 | struct mtd_oob_ops devops = *ops; |
247 | int i, err; | 248 | int i, err, ret = 0; |
248 | 249 | ||
249 | ops->retlen = 0; | 250 | ops->retlen = 0; |
250 | 251 | ||
@@ -262,12 +263,24 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) | |||
262 | 263 | ||
263 | err = subdev->read_oob(subdev, from, &devops); | 264 | err = subdev->read_oob(subdev, from, &devops); |
264 | ops->retlen += devops.retlen; | 265 | ops->retlen += devops.retlen; |
265 | if (err) | 266 | |
266 | return err; | 267 | /* Save information about bitflips! */ |
268 | if (unlikely(err)) { | ||
269 | if (err == -EBADMSG) { | ||
270 | mtd->ecc_stats.failed++; | ||
271 | ret = err; | ||
272 | } else if (err == -EUCLEAN) { | ||
273 | mtd->ecc_stats.corrected++; | ||
274 | /* Do not overwrite -EBADMSG !! */ | ||
275 | if (!ret) | ||
276 | ret = err; | ||
277 | } else | ||
278 | return err; | ||
279 | } | ||
267 | 280 | ||
268 | devops.len = ops->len - ops->retlen; | 281 | devops.len = ops->len - ops->retlen; |
269 | if (!devops.len) | 282 | if (!devops.len) |
270 | return 0; | 283 | return ret; |
271 | 284 | ||
272 | if (devops.datbuf) | 285 | if (devops.datbuf) |
273 | devops.datbuf += devops.retlen; | 286 | devops.datbuf += devops.retlen; |
@@ -655,6 +668,8 @@ static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
655 | } | 668 | } |
656 | 669 | ||
657 | err = subdev->block_markbad(subdev, ofs); | 670 | err = subdev->block_markbad(subdev, ofs); |
671 | if (!err) | ||
672 | mtd->ecc_stats.badblocks++; | ||
658 | break; | 673 | break; |
659 | } | 674 | } |
660 | 675 | ||
@@ -717,6 +732,8 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c | |||
717 | if (subdev[0]->block_markbad) | 732 | if (subdev[0]->block_markbad) |
718 | concat->mtd.block_markbad = concat_block_markbad; | 733 | concat->mtd.block_markbad = concat_block_markbad; |
719 | 734 | ||
735 | concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks; | ||
736 | |||
720 | concat->subdev[0] = subdev[0]; | 737 | concat->subdev[0] = subdev[0]; |
721 | 738 | ||
722 | for (i = 1; i < num_devs; i++) { | 739 | for (i = 1; i < num_devs; i++) { |
@@ -744,6 +761,8 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c | |||
744 | subdev[i]->flags & MTD_WRITEABLE; | 761 | subdev[i]->flags & MTD_WRITEABLE; |
745 | } | 762 | } |
746 | concat->mtd.size += subdev[i]->size; | 763 | concat->mtd.size += subdev[i]->size; |
764 | concat->mtd.ecc_stats.badblocks += | ||
765 | subdev[i]->ecc_stats.badblocks; | ||
747 | if (concat->mtd.writesize != subdev[i]->writesize || | 766 | if (concat->mtd.writesize != subdev[i]->writesize || |
748 | concat->mtd.oobsize != subdev[i]->oobsize || | 767 | concat->mtd.oobsize != subdev[i]->oobsize || |
749 | concat->mtd.ecctype != subdev[i]->ecctype || | 768 | concat->mtd.ecctype != subdev[i]->ecctype || |