mtd: nand: improve flash-based BBT robustness
cover mtd: nand: improve flash-based BBT robustness
Hello,
This patch series aims to improve the robustness of flash-based bad block tables, especially their ECC handling. In fact, most of the patches simply build up to the changes in patch 9 and 10, with some following bugfixes and improvements that were discovered as a result of the optimizations.
It's worth noting here the intended block scrubbing policy so that it can be checked for soundness and for implementation:
*) a BBT page with uncorrected ECC errors is invalid
*) a BBT page with corrected ECC errors is valid but needs scrubbing
(erased and rewritten with corrected data)
Upon discovering invalid table page(s), we retry our table versioning in this order:
(1) Mirrored table of same version
(2) Mirrored table of lesser version
(3) Rescan flash for bad blocks
After yielding the most up-to-date table (from table in flash or from scanning the device), then if the flash-BBT is out of date or needs scrubbing, the table should be rewritten.
Let me know how any of this works and if there are particular areas where documentation or explanation is lacking.
Brian
Brian Norris (14):
mtd: nand: refactor scanning code
mtd: nand: do not ignore all ECC errors
mtd: define `is_ecc_error()' macros
mtd: utilize `is_ecc_error()' macros
mtd: nand: remove unnecessary variable
mtd: nand: fix style
mtd: nand: begin restructuring check_create
mtd: nand: remove gotos in `check_create()'
mtd: nand: report ECC errors properly when reading BBT
mtd: nand: scrub BBT on ECC errors
mtd: nand: wait to set BBT version
mtd: nand: do not scan bad blocks with NAND_BBT_NO_OOB set
mtd: nand: invalidate cache on unaligned reads
mtd: nand: switch check_pattern()' to standard memcmp()'
drivers/mtd/inftlcore.c | 4 +- drivers/mtd/mtdchar.c | 4 +- drivers/mtd/mtdconcat.c | 8 +- drivers/mtd/mtdoops.c | 2 +- drivers/mtd/mtdpart.c | 8 +- drivers/mtd/mtdswap.c | 20 ++-- drivers/mtd/nand/diskonchip.c | 2 +- drivers/mtd/nand/nand_base.c | 12 ++- drivers/mtd/nand/nand_bbt.c | 198 ++++++++++++++++++----------------- drivers/mtd/nftlcore.c | 4 +- drivers/mtd/onenand/onenand_base.c | 11 +- drivers/mtd/sm_ftl.c | 4 +- drivers/mtd/tests/mtd_pagetest.c | 28 +++--- drivers/mtd/tests/mtd_readtest.c | 2 +- drivers/mtd/tests/mtd_speedtest.c | 8 +- drivers/mtd/tests/mtd_stresstest.c | 2 +- drivers/mtd/tests/mtd_subpagetest.c | 9 +- drivers/mtd/tests/mtd_torturetest.c | 2 +- drivers/mtd/ubi/eba.c | 2 +- drivers/mtd/ubi/io.c | 27 +++-- drivers/mtd/ubi/kapi.c | 3 +- drivers/mtd/ubi/misc.c | 2 +- drivers/mtd/ubi/scan.c | 4 +- drivers/mtd/ubi/vtbl.c | 2 +- include/linux/mtd/mtd.h | 5 + 25 files changed, 198 insertions(+), 175 deletions(-)
Signature · 1 line
1.7.5.4
PATCH 1/14 mtd: nand: refactor scanning code
A few pieces of code are unnecessarily duplicated. For easier maintenance, we should fix this.
This should have no functional effect.
--- drivers/mtd/nand/nand_bbt.c | 26 +++++++------------------- 1 files changed, 7 insertions(+), 19 deletions(-)
drivers/mtd/nand/nand_bbt.c +8 -20
@@ -306,28 +306,16 @@ static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, ops.ooboffs =0 ; ops.ooblen = mtd->oobsize; -while (len >0 ) { -if (len <= mtd->writesize) { - ops.oobbuf = buf + len; - ops.datbuf = buf; - ops.len = len; - res = mtd->read_oob (mtd, offs, &ops); - -/* Ignore ECC errors when checking for BBM */ -if (res != -EUCLEAN && res != -EBADMSG ) -return res; -return 0 ; - }else { - ops.oobbuf = buf + mtd->writesize; - ops.datbuf = buf; - ops.len = mtd->writesize; - res = mtd->read_oob (mtd, offs, &ops); + ops.datbuf = buf; + ops.len =min (len, (size_t )mtd->writesize); + ops.oobbuf = buf + ops.len; -/* Ignore ECC errors when checking for BBM */ -if (res && res != -EUCLEAN && res != -EBADMSG ) -return res; - } + res = mtd->read_oob (mtd, offs, &ops); + +/* Ignore ECC errors when checking for BBM */ +if (res && res != -EUCLEAN && res != -EBADMSG ) +return res; buf += mtd->oobsize + mtd->writesize; len -= mtd->writesize;
Signature · 1 line
1.7.5.4
Artem Bityutskiy
AppliedRe: [PATCH 01/14] mtd: nand: refactor scanning code
Quoted 6 lines · Brian Norris
A few pieces of code are unnecessarily duplicated. For easier maintenance, we should fix this.
This should have no functional effect.
Signed-off-by Brian Norris <[email protected]>
Pushed to my tree, thanks!
Signature · 2 lines
Best Regards, Artem Bityutskiy
PATCH 2/14 mtd: nand: do not ignore all ECC errors
In reply to Brian NorrisThere are a few reasons not to ignore ECC errors here.
First, mtd->read_oob is being called in raw mode, so there should be no error correction in the first place.
Second, if we change this such that there *is* error correction in this function, then we will want to pass the error message upward.
In fact, the code I introduced to "ignore ECC errors" would have been better if it had just placed this test down in `scan_block_full()' in the first place. We would like to ignore ECC errors when we are simply checking for bad block markers (e.g., factory marked), but we may not want to ignore ECC errors when scanning OOB for a flash-based BBT pattern (in scan_read_raw()'; note that the return codes from scan_read_raw()' are not actually handled yet).
--- drivers/mtd/nand/nand_bbt.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
drivers/mtd/nand/nand_bbt.c +3 -3
@@ -313,8 +313,7 @@ static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, res = mtd->read_oob (mtd, offs, &ops); -/* Ignore ECC errors when checking for BBM */ -if (res && res != -EUCLEAN && res != -EBADMSG ) +if (res)return res; buf += mtd->oobsize + mtd->writesize;
@@ -400,7 +399,8 @@ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,int ret, j; ret =scan_read_raw_oob (mtd, buf, offs, readlen); -if (ret) +/* Ignore ECC errors when checking for BBM */ +if (ret && ret != -EUCLEAN && ret != -EBADMSG )return ret;for (j =0 ; j < len; j++, buf += scanlen) {
Signature · 1 line
1.7.5.4
Artem Bityutskiy
AppliedRe: [PATCH 02/14] mtd: nand: do not ignore all ECC errors
Quoted 16 lines · Brian Norris
There are a few reasons not to ignore ECC errors here.
First,
mtd->read_oobis being called in raw mode, so there should be no error correction in the first place.Second, if we change this such that there *is* error correction in this function, then we will want to pass the error message upward.
In fact, the code I introduced to "ignore ECC errors" would have been better if it had just placed this test down in `scan_block_full()' in the first place. We would like to ignore ECC errors when we are simply checking for bad block markers (e.g., factory marked), but we may not want to ignore ECC errors when scanning OOB for a flash-based BBT pattern (in
scan_read_raw()'; note that the return codes fromscan_read_raw()' are not actually handled yet).
Quoted 1 line
Signed-off-by Brian Norris <[email protected]>
Pushed to my tree, thanks!
Signature · 2 lines
Best Regards, Artem Bityutskiy
PATCH 3/14 mtd: define `is_ecc_error()' macros
In reply to Brian NorrisThese macros can be used instead of including -EUCLEAN and -EBADMSG all over the place. They should help make code a little bit more readable.
--- include/linux/mtd/mtd.h | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
include/linux/mtd/mtd.h +5 -0
@@ -348,4 +348,9 @@ void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);void mtd_erase_callback (struct erase_info *instr); +#define is_corrected_ecc_error (error) (error == -EUCLEAN) +#define is_uncorrected_ecc_error (error) (error == -EBADMSG) +#define is_ecc_error (error) ((is_corrected_ecc_error(error) || \ + is_uncorrected_ecc_error(error))) +#endif /* __MTD_MTD_H__ */
Signature · 1 line
1.7.5.4
Re: [PATCH 03/14] mtd: define `is_ecc_error()' macros
Quoted 13 lines · Brian Norris
These macros can be used instead of including
-EUCLEANand-EBADMSGall over the place. They should help make code a little bit more readable.Signed-off-by Brian Norris <[email protected]>--- include/linux/mtd/mtd.h | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)include/linux/mtd/mtd.h +0
-0
include/linux/mtd/mtd.h void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size); · line 351
Quoted 4 lines
include/linux/mtd/mtd.h +1
-0@@ -348,4 +348,9 @@ void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);void mtd_erase_callback (struct erase_info *instr); +#define is_corrected_ecc_error (error) (error == -EUCLEAN)
This is not really an error...
include/linux/mtd/mtd.h void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size); · line 354
Quoted 3 lines
include/linux/mtd/mtd.h +3
-0+#define is_uncorrected_ecc_error (error) (error == -EBADMSG) +#define is_ecc_error (error) ((is_corrected_ecc_error(error) || \ + is_uncorrected_ecc_error(error)))
Could we please have static inline functions instead of macros?
I think it is nicer to have mtd_ prefixes, how about these names instead:
mtd_is_bitflip()mtd_is_eccerr()mtd_is_bitflip_or_eccerr()
Signature · 2 lines
Best Regards, Artem Bityutskiy
Re: [PATCH 03/14] mtd: define `is_ecc_error()' macros
Quoted 10 lines · Artem Bityutskiy
Quoted 1 line
+#define
is_corrected_ecc_error(error)(error ==-EUCLEAN)This is not really an error...
include/linux/mtd/mtd.h void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size); · line 354
Quoted 3 lines
include/linux/mtd/mtd.h +3
-0+#define is_uncorrected_ecc_error (error) (error == -EBADMSG) +#define is_ecc_error (error) ((is_corrected_ecc_error(error) || \ + is_uncorrected_ecc_error(error)))Could we please have static inline functions instead of macros?
Quoted 6 lines
I think it is nicer to have
mtd_prefixes, how about these names instead:
mtd_is_bitflip()mtd_is_eccerr()mtd_is_bitflip_or_eccerr()
Brian, I was actually waiting for v2 of the patches: 3/14, and 9/14-14/14.
Signature · 2 lines
Best Regards, Artem Bityutskiy
Re: [PATCH 03/14] mtd: define `is_ecc_error()' macros
Quoted 4 lines · Artem Bityutskiy
Quoted 3 lines · Artem Bityutskiy
Quoted 1 line
+#define
is_corrected_ecc_error(error)(error ==-EUCLEAN)This is not really an error...
I suppose I was just considering the names as describing the error code, even if it's not fully an error.
Quoted 5 lines
Quoted 5 lines
include/linux/mtd/mtd.h void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size); · line 354
Quoted 3 lines
include/linux/mtd/mtd.h +3
-0+#define is_uncorrected_ecc_error (error) (error == -EBADMSG) +#define is_ecc_error (error) ((is_corrected_ecc_error(error) || \ + is_uncorrected_ecc_error(error)))Could we please have static inline functions instead of macros?
Of course we can! Is there a particular reason? Better type checking? Or just kernel style? I don't think I see a code-size benefit...
Quoted 9 lines
Quoted 6 lines
I think it is nicer to have
mtd_prefixes, how about these names instead:
mtd_is_bitflip()mtd_is_eccerr()mtd_is_bitflip_or_eccerr()Brian, I was actually waiting for v2 of the patches: 3/14, and 9/14-14/14.
Right, I hadn't settled on a name yet and so I haven't rewritten the patches.
I like the fact that your names are shorter. I'm not sure about `mtd_is_bitflip_or_eccerr()', though; the compound name seems a little out of place. But maybe it's just better to be clear on exactly what is covered by the function. Is there a broad category name for bitflips/ECC errors? I just consider them corrected/uncorrected errors in flash, thus the naming I gave.
I'll either repost with a better naming scheme or update my patches with the suggested names.
Brian
Re: [PATCH 03/14] mtd: define `is_ecc_error()' macros
Quoted 11 lines · Brian Norris
Right, I hadn't settled on a name yet and so I haven't rewritten the patches.
I like the fact that your names are shorter. I'm not sure about `mtd_is_bitflip_or_eccerr()', though; the compound name seems a little out of place. But maybe it's just better to be clear on exactly what is covered by the function. Is there a broad category name for bitflips/ECC errors? I just consider them corrected/uncorrected errors in flash, thus the naming I gave.
I'll either repost with a better naming scheme or update my patches with the suggested names.
OK, let's do this sooner than later please, to make sure I have all your work in my tree, which is safer (consider the situation when dwmw2 picks what I have now and upstreams before we put everything in).
Signature · 2 lines
Best Regards, Artem Bityutskiy
PATCH v2 3/14 mtd: define `mtd_is_*()' functions
These functions can be used instead of referencing -EUCLEAN and -EBADMSG all over the place. They should help make code a little bit more readable.
---
v2: use static inline functions, change names to `mtd_is_*' prefix,
don't call bitflips "errors"
include/linux/mtd/mtd.h | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-)
include/linux/mtd/mtd.h +12 -0
@@ -348,4 +348,16 @@ void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);void mtd_erase_callback (struct erase_info *instr); +static inline int mtd_is_bitflip (int err) { +return err == -EUCLEAN ; +} + +static inline int mtd_is_eccerr (int err) { +return err == -EBADMSG ; +} + +static inline int mtd_is_bitflip_or_eccerr (int err) { +return mtd_is_bitflip (err) ||mtd_is_eccerr (err); +} +#endif /* __MTD_MTD_H__ */
Signature · 1 line
1.7.5.4
Re: [PATCH 03/14] mtd: define `is_ecc_error()' macros
In reply to Artem BityutskiyQuoted 6 lines · Artem Bityutskiy
Quoted 2 lines
I'll either repost with a better naming scheme or update my patches with the suggested names.
OK, let's do this sooner than later please, to make sure I have all your work in my tree, which is safer (consider the situation when dwmw2 picks what I have now and upstreams before we put everything in).
OK, I sent the necessary v2 patches. I just went with your names for lack of a better idea.
I didn't send v2 of patches 13/14 and 14/14, since there was no dependency. Let me know if I need to resend anything else.
Brian
Re: [PATCH 03/14] mtd: define `is_ecc_error()' macros
Quoted 8 lines · Brian Norris
Quoted 6 lines · Artem Bityutskiy
Quoted 2 lines
I'll either repost with a better naming scheme or update my patches with the suggested names.
OK, let's do this sooner than later please, to make sure I have all your work in my tree, which is safer (consider the situation when dwmw2 picks what I have now and upstreams before we put everything in).
Quoted 5 lines
OK, I sent the necessary v2 patches. I just went with your names for lack of a better idea.
I didn't send v2 of patches 13/14 and 14/14, since there was no dependency. Let me know if I need to resend anything else.
Pushed, thanks for great job!
Signature · 2 lines
Best Regards, Artem Bityutskiy
PATCH 4/14 mtd: utilize `is_ecc_error()' macros
In reply to Brian Norris--- drivers/mtd/inftlcore.c | 4 ++-- drivers/mtd/mtdchar.c | 4 ++-- drivers/mtd/mtdconcat.c | 8 ++++---- drivers/mtd/mtdoops.c | 2 +- drivers/mtd/mtdpart.c | 8 ++++---- drivers/mtd/mtdswap.c | 20 ++++++++++---------- drivers/mtd/nand/diskonchip.c | 2 +- drivers/mtd/nand/nand_bbt.c | 4 ++-- drivers/mtd/nftlcore.c | 4 ++-- drivers/mtd/onenand/onenand_base.c | 11 ++++++----- drivers/mtd/sm_ftl.c | 4 ++-- drivers/mtd/tests/mtd_pagetest.c | 28 ++++++++++++++-------------- drivers/mtd/tests/mtd_readtest.c | 2 +- drivers/mtd/tests/mtd_speedtest.c | 8 ++++---- drivers/mtd/tests/mtd_stresstest.c | 2 +- drivers/mtd/tests/mtd_subpagetest.c | 9 +++++---- drivers/mtd/tests/mtd_torturetest.c | 2 +- drivers/mtd/ubi/eba.c | 2 +- drivers/mtd/ubi/io.c | 27 +++++++++++++++------------ drivers/mtd/ubi/kapi.c | 3 ++- drivers/mtd/ubi/misc.c | 2 +- drivers/mtd/ubi/scan.c | 4 ++-- drivers/mtd/ubi/vtbl.c | 2 +- 23 files changed, 84 insertions(+), 78 deletions(-)
drivers/mtd/inftlcore.c +2 -2
@@ -346,7 +346,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned ret = mtd->read (mtd, (inftl->EraseSize * BlockMap[block]) + (block *SECTORSIZE ),SECTORSIZE , &retlen, movebuf); -if (ret <0 && ret != -EUCLEAN ) { +if (ret <0 && !is_corrected_ecc_error (ret)) { ret = mtd->read(mtd, (inftl->EraseSize * BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE,
@@ -917,7 +917,7 @@ foundit:int ret = mtd->read (mtd, ptr,SECTORSIZE , &retlen, buffer);/* Handle corrected bit flips gracefully */ -if (ret <0 && ret != -EUCLEAN ) +if (ret <0 && !is_corrected_ecc_error (ret))return -EIO ; }return 0 ;
drivers/mtd/mtdchar.c +2 -2
@@ -242,7 +242,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t* Userspace software which accesses NAND this way * must be aware of the fact that it deals with NAND */ -if (!ret || (ret == -EUCLEAN ) || (ret == -EBADMSG )) { +if (!ret ||is_ecc_error (ret)) { *ppos += retlen;if (copy_to_user (buf, kbuf, retlen)) {kfree (kbuf);
@@ -491,7 +491,7 @@ static int mtd_do_readoob(struct file *file, struct mtd_info *mtd,* does not calculate ECC for the OOB area, so do not rely on * this behavior unless you have replaced it with your own. */ -if (ret == -EUCLEAN || ret == -EBADMSG ) +if (is_ecc_error (ret))return 0 ;return ret;
drivers/mtd/mtdconcat.c +4 -4
@@ -95,10 +95,10 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len,/* Save information about bitflips! */ if (unlikely (err)) { -if (err == -EBADMSG ) { +if (is_uncorrected_ecc_error (err)) { mtd->ecc_stats.failed++; ret = err; - }else if (err == -EUCLEAN ) { + }else if (is_corrected_ecc_error (err)) { mtd->ecc_stats.corrected++;/* Do not overwrite -EBADMSG !! */ if (!ret)
@@ -279,10 +279,10 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)/* Save information about bitflips! */ if (unlikely (err)) { -if (err == -EBADMSG ) { +if (is_uncorrected_ecc_error (err)) { mtd->ecc_stats.failed++; ret = err; - }else if (err == -EUCLEAN ) { + }else if (is_corrected_ecc_error (err)) { mtd->ecc_stats.corrected++;/* Do not overwrite -EBADMSG !! */ if (!ret)
drivers/mtd/mtdoops.c +1 -1
@@ -258,7 +258,7 @@ static void find_next_position(struct mtdoops_context *cxt) ret = mtd->read (mtd, page * record_size,MTDOOPS_HEADER_SIZE , &retlen, (u_char *) &count[0 ]);if (retlen !=MTDOOPS_HEADER_SIZE || - (ret <0 && ret != -EUCLEAN )) { + (ret <0 && !is_corrected_ecc_error (ret))) {printk (KERN_ERR "mtdoops: read failure at %ld (%td of %d read), err %d\n" , page * record_size, retlen,MTDOOPS_HEADER_SIZE , ret);
drivers/mtd/mtdpart.c +4 -4
@@ -73,9 +73,9 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len, res = part->master->read (part->master, from + part->offset, len, retlen, buf);if (unlikely (res)) { -if (res == -EUCLEAN ) +if (is_corrected_ecc_error (res)) mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected; -if (res == -EBADMSG ) +if (is_uncorrected_ecc_error (res)) mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed; }return res;
@@ -142,9 +142,9 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from, res = part->master->read_oob (part->master, from + part->offset, ops);if (unlikely (res)) { -if (res == -EUCLEAN ) +if (is_corrected_ecc_error (res)) mtd->ecc_stats.corrected++; -if (res == -EBADMSG ) +if (is_uncorrected_ecc_error (res)) mtd->ecc_stats.failed++; }return res;
drivers/mtd/mtdswap.c +10 -10
@@ -314,7 +314,7 @@ static int mtdswap_read_oob(struct mtdswap_dev *d, loff_t from, {int ret = d->mtd->read_oob (d->mtd, from, ops); -if (ret == -EUCLEAN ) +if (is_corrected_ecc_error (ret))return ret;if (ret) {
@@ -354,7 +354,7 @@ static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb) ret =mtdswap_read_oob (d, offset, &ops); -if (ret && ret != -EUCLEAN ) +if (ret && !is_corrected_ecc_error (ret))return ret; data = (struct mtdswap_oobdata *)d->oob_buf;
@@ -363,7 +363,7 @@ static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb)if (le16_to_cpu (data->magic) ==MTDSWAP_MAGIC_CLEAN ) { eb->erase_count =le32_to_cpu (data->count); -if (ret == -EUCLEAN ) +if (is_corrected_ecc_error (ret)) ret =MTDSWAP_SCANNED_BITFLIP ;else {if (le16_to_cpu (data2->magic) ==MTDSWAP_MAGIC_DIRTY )
@@ -408,7 +408,7 @@ static int mtdswap_write_marker(struct mtdswap_dev *d, struct swap_eb *eb,if (ret) {dev_warn (d->dev,"Write OOB failed for block at %08llx " "error %d\n" , offset, ret); -if (ret == -EIO || ret == -EBADMSG ) +if (ret == -EIO ||is_uncorrected_ecc_error (ret))mtdswap_handle_write_error (d, eb);return ret; }
@@ -628,7 +628,7 @@ static int mtdswap_map_free_block(struct mtdswap_dev *d, unsigned int page,TREE_COUNT (d,CLEAN )--; ret =mtdswap_write_marker (d, eb,MTDSWAP_TYPE_DIRTY ); - }while (ret == -EIO || ret == -EBADMSG ); + }while (ret == -EIO ||is_uncorrected_ecc_error (ret));if (ret)return ret;
@@ -678,7 +678,7 @@ retry: ret =mtdswap_map_free_block (d, page, bp); eb = d->eb_data + (*bp / d->pages_per_eblk); -if (ret == -EIO || ret == -EBADMSG ) { +if (ret == -EIO ||is_uncorrected_ecc_error (ret)) { d->curr_write =NULL ; eb->active_count--; d->revmap[*bp] =PAGE_UNDEF ;
@@ -690,7 +690,7 @@ retry: writepos = (loff_t)*bp <<PAGE_SHIFT ; ret = mtd->write (mtd, writepos,PAGE_SIZE , &retlen, buf); -if (ret == -EIO || ret == -EBADMSG ) { +if (ret == -EIO ||is_uncorrected_ecc_error (ret)) { d->curr_write_pos--; eb->active_count--; d->revmap[*bp] =PAGE_UNDEF ;
@@ -738,7 +738,7 @@ static int mtdswap_move_block(struct mtdswap_dev *d, unsigned int oldblock, retry: ret = mtd->read (mtd, readpos,PAGE_SIZE , &retlen, d->page_buf); -if (ret <0 && ret != -EUCLEAN ) { +if (ret <0 && !is_corrected_ecc_error (ret)) { oldeb = d->eb_data + oldblock / d->pages_per_eblk; oldeb->flags |=EBLOCK_READERR ;
@@ -1016,7 +1016,7 @@ static int mtdswap_gc(struct mtdswap_dev *d, unsigned int background)if (ret ==0 )mtdswap_rb_add (d, eb,MTDSWAP_CLEAN ); -else if (ret != -EIO && ret != -EBADMSG ) +else if (ret != -EIO && !is_uncorrected_ecc_error (ret))mtdswap_rb_add (d, eb,MTDSWAP_DIRTY );return 0 ;
@@ -1164,7 +1164,7 @@ retry: ret = mtd->read (mtd, readpos,PAGE_SIZE , &retlen, buf); d->mtd_read_count++; -if (ret == -EUCLEAN ) { +if (is_corrected_ecc_error (ret)) { eb->flags |=EBLOCK_BITFLIP ;mtdswap_rb_add (d, eb,MTDSWAP_BITFLIP ); ret =0 ;
drivers/mtd/nand/diskonchip.c +1 -1
@@ -1031,7 +1031,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,WriteDOC (DOC_ECC_DIS , docptr, Mplus_ECCConf); elseWriteDOC (DOC_ECC_DIS ,docptr ,ECCConf ); -if (no_ecc_failures && (ret == -EBADMSG )) { +if (no_ecc_failures &&is_uncorrected_ecc_error (ret)) {printk (KERN_ERR "suppressing ECC failure\n" ); ret =0 ; }
drivers/mtd/nand/nand_bbt.c +2 -2
@@ -400,7 +400,7 @@ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, ret =scan_read_raw_oob (mtd, buf, offs, readlen);/* Ignore ECC errors when checking for BBM */ -if (ret && ret != -EUCLEAN && ret != -EBADMSG ) +if (ret && !is_ecc_error (ret))return ret;for (j =0 ; j < len; j++, buf += scanlen) {
@@ -430,7 +430,7 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,*/ ret = mtd->read_oob (mtd, offs, &ops);/* Ignore ECC errors when checking for BBM */ -if (ret && ret != -EUCLEAN && ret != -EBADMSG ) +if (ret && !is_ecc_error (ret))return ret;if (check_short_pattern (buf, bd))
drivers/mtd/nftlcore.c +2 -2
@@ -425,7 +425,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p ret = mtd->read (mtd, (nftl->EraseSize * BlockMap[block]) + (block *512 ),512 , &retlen, movebuf); -if (ret <0 && ret != -EUCLEAN ) { +if (ret <0 && !is_corrected_ecc_error (ret)) { ret = mtd->read (mtd, (nftl->EraseSize * BlockMap[block]) + (block *512 ),512 , &retlen, movebuf);
@@ -773,7 +773,7 @@ static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,size_t retlen;int res = mtd->read (mtd, ptr,512 , &retlen, buffer); -if (res <0 && res != -EUCLEAN ) +if (res <0 && !is_corrected_ecc_error (res))return -EIO ; }return 0 ;
drivers/mtd/onenand/onenand_base.c +6 -5
@@ -1079,7 +1079,8 @@ static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int status)return status;/* check if we failed due to uncorrectable error */ -if (status != -EBADMSG && status !=ONENAND_BBT_READ_ECC_ERROR ) +if (!is_uncorrected_ecc_error (status) && + status !=ONENAND_BBT_READ_ECC_ERROR )return status;/* check if address lies in MLC region */
@@ -1159,7 +1160,7 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from,if (unlikely (ret)) ret =onenand_recover_lsb (mtd, from, ret);onenand_update_bufferram (mtd, from, !ret); -if (ret == -EBADMSG ) +if (is_uncorrected_ecc_error (ret)) ret =0 ;if (ret)break ;
@@ -1255,7 +1256,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, this->command (mtd,ONENAND_CMD_READ , from, writesize); ret = this->wait (mtd,FL_READING );onenand_update_bufferram (mtd, from, !ret); -if (ret == -EBADMSG ) +if (is_uncorrected_ecc_error (ret)) ret =0 ; } }
@@ -1315,7 +1316,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,/* Now wait for load */ ret = this->wait (mtd,FL_READING );onenand_update_bufferram (mtd, from, !ret); -if (ret == -EBADMSG ) +if (is_uncorrected_ecc_error (ret)) ret =0 ; }
@@ -1403,7 +1404,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,if (unlikely (ret)) ret =onenand_recover_lsb (mtd, from, ret); -if (ret && ret != -EBADMSG ) { +if (ret && !is_uncorrected_ecc_error (ret)) {printk (KERN_ERR "%s: read failed = 0x%x\n" , __func__, ret);break ;
drivers/mtd/sm_ftl.c +2 -2
@@ -281,7 +281,7 @@ again: ret = mtd->read_oob (mtd,sm_mkoffset (ftl, zone, block, boffset), &ops);/* Test for unknown errors */ -if (ret !=0 && ret != -EUCLEAN && ret != -EBADMSG ) { +if (ret !=0 && !is_ecc_error (ret)) {dbg ("read of block %d at zone %d, failed due to error (%d)" , block, zone, ret); goto again;
@@ -306,7 +306,7 @@ again: }/* Test ECC*/ -if (ret == -EBADMSG || +if (is_uncorrected_ecc_error (ret) || (ftl->smallpagenand &&sm_correct_sector (buffer, oob))) { dbg("read of block %d at zone %d, failed due to ECC error",
drivers/mtd/tests/mtd_pagetest.c +14 -14
@@ -128,7 +128,7 @@ static int verify_eraseblock(int ebnum)for (j =0 ; j < pgcnt -1 ; ++j, addr += pgsize) {/* Do a read to set the internal dataRAMs to different data */ err = mtd->read (mtd, addr0, bufsize, &read, twopages); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != bufsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -136,7 +136,7 @@ static int verify_eraseblock(int ebnum)return err; } err = mtd->read (mtd, addrn - bufsize, bufsize, &read, twopages); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != bufsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -146,7 +146,7 @@ static int verify_eraseblock(int ebnum)memset (twopages,0 , bufsize); read =0 ; err = mtd->read (mtd, addr, bufsize, &read, twopages); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != bufsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -164,7 +164,7 @@ static int verify_eraseblock(int ebnum)unsigned long oldnext = next;/* Do a read to set the internal dataRAMs to different data */ err = mtd->read (mtd, addr0, bufsize, &read, twopages); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != bufsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -172,7 +172,7 @@ static int verify_eraseblock(int ebnum)return err; } err = mtd->read (mtd, addrn - bufsize, bufsize, &read, twopages); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != bufsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -182,7 +182,7 @@ static int verify_eraseblock(int ebnum)memset (twopages,0 , bufsize); read =0 ; err = mtd->read (mtd, addr, bufsize, &read, twopages); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != bufsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -231,7 +231,7 @@ static int crosstest(void) read =0 ; addr = addrn - pgsize - pgsize; err = mtd->read (mtd, addr, pgsize, &read, pp1); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -244,7 +244,7 @@ static int crosstest(void) read =0 ; addr = addrn - pgsize - pgsize - pgsize; err = mtd->read (mtd, addr, pgsize, &read, pp1); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -258,7 +258,7 @@ static int crosstest(void) addr = addr0;printk (PRINT_PREF "reading page at %#llx\n" , (long long )addr); err = mtd->read (mtd, addr, pgsize, &read, pp2); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -272,7 +272,7 @@ static int crosstest(void) addr = addrn - pgsize;printk (PRINT_PREF "reading page at %#llx\n" , (long long )addr); err = mtd->read (mtd, addr, pgsize, &read, pp3); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -286,7 +286,7 @@ static int crosstest(void) addr = addr0;printk (PRINT_PREF "reading page at %#llx\n" , (long long )addr); err = mtd->read (mtd, addr, pgsize, &read, pp4); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -345,7 +345,7 @@ static int erasecrosstest(void)printk (PRINT_PREF "reading 1st page of block %d\n" , ebnum);memset (readbuf,0 , pgsize); err = mtd->read (mtd, addr0, pgsize, &read, readbuf); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -383,7 +383,7 @@ static int erasecrosstest(void)printk (PRINT_PREF "reading 1st page of block %d\n" , ebnum);memset (readbuf,0 , pgsize); err = mtd->read (mtd, addr0, pgsize, &read, readbuf); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -439,7 +439,7 @@ static int erasetest(void)printk (PRINT_PREF "reading 1st page of block %d\n" , ebnum); err = mtd->read (mtd, addr0, pgsize, &read, twopages); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
drivers/mtd/tests/mtd_readtest.c +1 -1
@@ -75,7 +75,7 @@ static int read_eraseblock_by_page(int ebnum) ops.datbuf =NULL ; ops.oobbuf = oobbuf; ret = mtd->read_oob (mtd, addr, &ops); -if ((ret && ret != -EUCLEAN ) || +if ((ret && !is_corrected_ecc_error (ret)) || ops.oobretlen != mtd->oobsize) {printk (PRINT_PREF "error: read oob failed at " "%#llx\n" , (long long )addr);
drivers/mtd/tests/mtd_speedtest.c +4 -4
@@ -216,7 +216,7 @@ static int read_eraseblock(int ebnum) err = mtd->read (mtd, addr, mtd->erasesize, &read, iobuf);/* Ignore corrected ECC errors */ -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != mtd->erasesize) {printk (PRINT_PREF "error: read failed at %#llx\n" , addr);
@@ -237,7 +237,7 @@ static int read_eraseblock_by_page(int ebnum)for (i =0 ; i < pgcnt; i++) { err = mtd->read (mtd, addr, pgsize, &read, buf);/* Ignore corrected ECC errors */ -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -263,7 +263,7 @@ static int read_eraseblock_by_2pages(int ebnum)for (i =0 ; i < n; i++) { err = mtd->read (mtd, addr, sz, &read, buf);/* Ignore corrected ECC errors */ -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != sz) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -278,7 +278,7 @@ static int read_eraseblock_by_2pages(int ebnum)if (pgcnt %2 ) { err = mtd->read (mtd, addr, pgsize, &read, buf);/* Ignore corrected ECC errors */ -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
drivers/mtd/tests/mtd_stresstest.c +1 -1
@@ -154,7 +154,7 @@ static int do_read(void) } addr = eb * mtd->erasesize + offs; err = mtd->read (mtd, addr, len, &read, readbuf); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err)) err =0 ;if (unlikely (err || read != len)) { printk(PRINT_PREF "error: read failed at 0x%llx\n",
drivers/mtd/tests/mtd_subpagetest.c +5 -4
@@ -198,7 +198,7 @@ static int verify_eraseblock(int ebnum) read =0 ; err = mtd->read (mtd, addr, subpgsize, &read, readbuf);if (unlikely (err || read != subpgsize)) { -if (err == -EUCLEAN && read == subpgsize) { +if (is_corrected_ecc_error (err) && read == subpgsize) {printk (PRINT_PREF "ECC correction at %#llx\n" , (long long )addr); err =0 ;
@@ -226,7 +226,7 @@ static int verify_eraseblock(int ebnum) read =0 ; err = mtd->read (mtd, addr, subpgsize, &read, readbuf);if (unlikely (err || read != subpgsize)) { -if (err == -EUCLEAN && read == subpgsize) { +if (is_corrected_ecc_error (err) && read == subpgsize) {printk (PRINT_PREF "ECC correction at %#llx\n" , (long long )addr); err =0 ;
@@ -264,7 +264,8 @@ static int verify_eraseblock2(int ebnum) read =0 ; err = mtd->read (mtd, addr, subpgsize * k, &read, readbuf);if (unlikely (err || read != subpgsize * k)) { -if (err == -EUCLEAN && read == subpgsize * k) { +if (is_corrected_ecc_error (err) && + read == subpgsize * k) {printk (PRINT_PREF "ECC correction at %#llx\n" , (long long )addr); err =0 ;
@@ -298,7 +299,7 @@ static int verify_eraseblock_ff(int ebnum) read =0 ; err = mtd->read (mtd, addr, subpgsize, &read, readbuf);if (unlikely (err || read != subpgsize)) { -if (err == -EUCLEAN && read == subpgsize) { +if (is_corrected_ecc_error (err) && read == subpgsize) {printk (PRINT_PREF "ECC correction at %#llx\n" , (long long )addr); err =0 ;
drivers/mtd/tests/mtd_torturetest.c +1 -1
@@ -138,7 +138,7 @@ static inline int check_eraseblock(int ebnum, unsigned char *buf) retry: err = mtd->read (mtd, addr, len, &read, check_buf); -if (err == -EUCLEAN ) +if (is_corrected_ecc_error (err))printk (PRINT_PREF "single bit flip occurred at EB %d " "MTD reported that it was fixed.\n" , ebnum);else if (err) {
drivers/mtd/ubi/eba.c +1 -1
@@ -443,7 +443,7 @@ retry:if (err ==UBI_IO_BITFLIPS ) { scrub =1 ; err =0 ; - }else if (err == -EBADMSG ) { + }else if (is_uncorrected_ecc_error (err)) {if (vol->vol_type ==UBI_DYNAMIC_VOLUME ) goto out_unlock; scrub =1 ;
drivers/mtd/ubi/io.c +15 -12
@@ -172,9 +172,10 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, retry: err = ubi->mtd->read (ubi->mtd, addr, len, &read, buf);if (err) { -const char *errstr = (err == -EBADMSG ) ?" (ECC error)" :"" ; +const char *errstr = +is_uncorrected_ecc_error (err) ?" (ECC error)" :"" ; -if (err == -EUCLEAN ) { +if (is_corrected_ecc_error (err)) {/* * -EUCLEAN is reported if there was a bit-flip which * was corrected, so this is harmless.
@@ -205,7 +206,7 @@ retry:* all the requested data. But some buggy drivers might do * this, so we change it to -EIO. */ -if (read != len && err == -EBADMSG ) { +if (read != len &&is_uncorrected_ecc_error (err)) {ubi_assert (0 ); err = -EIO ; }
@@ -469,7 +470,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum) out:mutex_unlock (&ubi->buf_mutex); -if (err ==UBI_IO_BITFLIPS || err == -EBADMSG ) { +if (err ==UBI_IO_BITFLIPS ||is_uncorrected_ecc_error (err)) {/* * If a bit-flip or data integrity error was detected, the test * has not passed because it happened on a freshly erased
@@ -760,7 +761,8 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, read_err =ubi_io_read (ubi, ec_hdr, pnum,0 ,UBI_EC_HDR_SIZE );if (read_err) { -if (read_err !=UBI_IO_BITFLIPS && read_err != -EBADMSG ) +if (read_err !=UBI_IO_BITFLIPS && + !is_uncorrected_ecc_error (read_err))return read_err;/*
@@ -776,7 +778,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, magic =be32_to_cpu (ec_hdr->magic);if (magic !=UBI_EC_HDR_MAGIC ) { -if (read_err == -EBADMSG ) +if (is_uncorrected_ecc_error (read_err))return UBI_IO_BAD_HDR_EBADMSG ;/*
@@ -1032,12 +1034,13 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, p = (char *)vid_hdr - ubi->vid_hdr_shift; read_err =ubi_io_read (ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); -if (read_err && read_err !=UBI_IO_BITFLIPS && read_err != -EBADMSG ) +if (read_err && read_err !=UBI_IO_BITFLIPS && + !is_uncorrected_ecc_error (read_err))return read_err; magic =be32_to_cpu (vid_hdr->magic);if (magic !=UBI_VID_HDR_MAGIC ) { -if (read_err == -EBADMSG ) +if (is_uncorrected_ecc_error (read_err))return UBI_IO_BAD_HDR_EBADMSG ;if (ubi_check_pattern (vid_hdr,0xFF ,UBI_VID_HDR_SIZE )) {
@@ -1219,7 +1222,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)return -ENOMEM ; err =ubi_io_read (ubi, ec_hdr, pnum,0 ,UBI_EC_HDR_SIZE ); -if (err && err !=UBI_IO_BITFLIPS && err != -EBADMSG ) +if (err && err !=UBI_IO_BITFLIPS && !is_uncorrected_ecc_error (err)) goto exit; crc =crc32 (UBI_CRC32_INIT , ec_hdr,UBI_EC_HDR_SIZE_CRC );
@@ -1306,7 +1309,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) p = (char *)vid_hdr - ubi->vid_hdr_shift; err =ubi_io_read (ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); -if (err && err !=UBI_IO_BITFLIPS && err != -EBADMSG ) +if (err && err !=UBI_IO_BITFLIPS && !is_uncorrected_ecc_error (err)) goto exit; crc =crc32 (UBI_CRC32_INIT , vid_hdr,UBI_EC_HDR_SIZE_CRC );
@@ -1358,7 +1361,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, } err = ubi->mtd->read (ubi->mtd, addr, len, &read, buf1); -if (err && err != -EUCLEAN ) +if (err && !is_corrected_ecc_error (err)) goto out_free;for (i =0 ; i < len; i++) {
@@ -1422,7 +1425,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) } err = ubi->mtd->read (ubi->mtd, addr, len, &read, buf); -if (err && err != -EUCLEAN ) { +if (err && !is_corrected_ecc_error (err)) {ubi_err ("error %d while reading %d bytes from PEB %d:%d, " "read %zd bytes" , err, len, pnum, offset, read); goto error;
drivers/mtd/ubi/kapi.c +2 -1
@@ -410,7 +410,8 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,return 0 ; err =ubi_eba_read_leb (ubi, vol, lnum, buf, offset, len, check); -if (err && err == -EBADMSG && vol->vol_type ==UBI_STATIC_VOLUME ) { +if (err &&is_uncorrected_ecc_error (err) + && vol->vol_type ==UBI_STATIC_VOLUME ) {ubi_warn ("mark volume %d as corrupted" , vol_id); vol->corrupted =1 ; }
drivers/mtd/ubi/misc.c +1 -1
@@ -81,7 +81,7 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id) err =ubi_eba_read_leb (ubi, vol, i, buf,0 , size,1 );if (err) { -if (err == -EBADMSG ) +if (is_uncorrected_ecc_error (err)) err =1 ;break ; }
drivers/mtd/ubi/scan.c +2 -2
@@ -395,7 +395,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, } err =ubi_io_read_data (ubi, buf, pnum,0 , len); -if (err && err !=UBI_IO_BITFLIPS && err != -EBADMSG ) +if (err && err !=UBI_IO_BITFLIPS && !is_uncorrected_ecc_error (err)) goto out_free_buf; data_crc =be32_to_cpu (vid_hdr->data_crc);
@@ -793,7 +793,7 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr, err =ubi_io_read (ubi, ubi->peb_buf1, pnum, ubi->leb_start, ubi->leb_size); -if (err ==UBI_IO_BITFLIPS || err == -EBADMSG ) { +if (err ==UBI_IO_BITFLIPS ||is_uncorrected_ecc_error (err)) {/* * Bit-flips or integrity errors while reading the data area. * It is difficult to say for sure what type of corruption is
drivers/mtd/ubi/vtbl.c +1 -1
@@ -423,7 +423,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, err =ubi_io_read_data (ubi, leb[seb->lnum], seb->pnum,0 , ubi->vtbl_size); -if (err ==UBI_IO_BITFLIPS || err == -EBADMSG ) +if (err ==UBI_IO_BITFLIPS ||is_uncorrected_ecc_error (err))/* * Scrub the PEB later. Note, -EBADMSG indicates an * uncorrectable ECC error, but we have our own CRC and
Signature · 1 line
1.7.5.4
PATCH v2 4/14 mtd: utilize `mtd_is_*()' functions
---
v2: change to `mtd_is_*' prefix
drivers/mtd/inftlcore.c | 4 ++-- drivers/mtd/mtdchar.c | 4 ++-- drivers/mtd/mtdconcat.c | 8 ++++---- drivers/mtd/mtdoops.c | 2 +- drivers/mtd/mtdpart.c | 8 ++++---- drivers/mtd/mtdswap.c | 20 ++++++++++---------- drivers/mtd/nand/diskonchip.c | 2 +- drivers/mtd/nand/nand_bbt.c | 4 ++-- drivers/mtd/nftlcore.c | 4 ++-- drivers/mtd/onenand/onenand_base.c | 10 +++++----- drivers/mtd/sm_ftl.c | 4 ++-- drivers/mtd/tests/mtd_pagetest.c | 28 ++++++++++++++-------------- drivers/mtd/tests/mtd_readtest.c | 2 +- drivers/mtd/tests/mtd_speedtest.c | 8 ++++---- drivers/mtd/tests/mtd_stresstest.c | 2 +- drivers/mtd/tests/mtd_subpagetest.c | 8 ++++---- drivers/mtd/tests/mtd_torturetest.c | 2 +- drivers/mtd/ubi/eba.c | 2 +- drivers/mtd/ubi/io.c | 24 ++++++++++++------------ drivers/mtd/ubi/kapi.c | 2 +- drivers/mtd/ubi/misc.c | 2 +- drivers/mtd/ubi/scan.c | 4 ++-- drivers/mtd/ubi/vtbl.c | 2 +- 23 files changed, 78 insertions(+), 78 deletions(-)
drivers/mtd/inftlcore.c +2 -2
@@ -346,7 +346,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned ret = mtd->read (mtd, (inftl->EraseSize * BlockMap[block]) + (block *SECTORSIZE ),SECTORSIZE , &retlen, movebuf); -if (ret <0 && ret != -EUCLEAN ) { +if (ret <0 && !mtd_is_bitflip (ret)) { ret = mtd->read(mtd, (inftl->EraseSize * BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE,
@@ -917,7 +917,7 @@ foundit:int ret = mtd->read (mtd, ptr,SECTORSIZE , &retlen, buffer);/* Handle corrected bit flips gracefully */ -if (ret <0 && ret != -EUCLEAN ) +if (ret <0 && !mtd_is_bitflip (ret))return -EIO ; }return 0 ;
drivers/mtd/mtdchar.c +2 -2
@@ -242,7 +242,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t* Userspace software which accesses NAND this way * must be aware of the fact that it deals with NAND */ -if (!ret || (ret == -EUCLEAN ) || (ret == -EBADMSG )) { +if (!ret ||mtd_is_bitflip_or_eccerr (ret)) { *ppos += retlen;if (copy_to_user (buf, kbuf, retlen)) {kfree (kbuf);
@@ -491,7 +491,7 @@ static int mtd_do_readoob(struct file *file, struct mtd_info *mtd,* does not calculate ECC for the OOB area, so do not rely on * this behavior unless you have replaced it with your own. */ -if (ret == -EUCLEAN || ret == -EBADMSG ) +if (mtd_is_bitflip_or_eccerr (ret))return 0 ;return ret;
drivers/mtd/mtdconcat.c +4 -4
@@ -95,10 +95,10 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len,/* Save information about bitflips! */ if (unlikely (err)) { -if (err == -EBADMSG ) { +if (mtd_is_eccerr (err)) { mtd->ecc_stats.failed++; ret = err; - }else if (err == -EUCLEAN ) { + }else if (mtd_is_bitflip (err)) { mtd->ecc_stats.corrected++;/* Do not overwrite -EBADMSG !! */ if (!ret)
@@ -279,10 +279,10 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)/* Save information about bitflips! */ if (unlikely (err)) { -if (err == -EBADMSG ) { +if (mtd_is_eccerr (err)) { mtd->ecc_stats.failed++; ret = err; - }else if (err == -EUCLEAN ) { + }else if (mtd_is_bitflip (err)) { mtd->ecc_stats.corrected++;/* Do not overwrite -EBADMSG !! */ if (!ret)
drivers/mtd/mtdoops.c +1 -1
@@ -258,7 +258,7 @@ static void find_next_position(struct mtdoops_context *cxt) ret = mtd->read (mtd, page * record_size,MTDOOPS_HEADER_SIZE , &retlen, (u_char *) &count[0 ]);if (retlen !=MTDOOPS_HEADER_SIZE || - (ret <0 && ret != -EUCLEAN )) { + (ret <0 && !mtd_is_bitflip (ret))) {printk (KERN_ERR "mtdoops: read failure at %ld (%td of %d read), err %d\n" , page * record_size, retlen,MTDOOPS_HEADER_SIZE , ret);
drivers/mtd/mtdpart.c +4 -4
@@ -73,9 +73,9 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len, res = part->master->read (part->master, from + part->offset, len, retlen, buf);if (unlikely (res)) { -if (res == -EUCLEAN ) +if (mtd_is_bitflip (res)) mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected; -if (res == -EBADMSG ) +if (mtd_is_eccerr (res)) mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed; }return res;
@@ -142,9 +142,9 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from, res = part->master->read_oob (part->master, from + part->offset, ops);if (unlikely (res)) { -if (res == -EUCLEAN ) +if (mtd_is_bitflip (res)) mtd->ecc_stats.corrected++; -if (res == -EBADMSG ) +if (mtd_is_eccerr (res)) mtd->ecc_stats.failed++; }return res;
drivers/mtd/mtdswap.c +10 -10
@@ -314,7 +314,7 @@ static int mtdswap_read_oob(struct mtdswap_dev *d, loff_t from, {int ret = d->mtd->read_oob (d->mtd, from, ops); -if (ret == -EUCLEAN ) +if (mtd_is_bitflip (ret))return ret;if (ret) {
@@ -354,7 +354,7 @@ static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb) ret =mtdswap_read_oob (d, offset, &ops); -if (ret && ret != -EUCLEAN ) +if (ret && !mtd_is_bitflip (ret))return ret; data = (struct mtdswap_oobdata *)d->oob_buf;
@@ -363,7 +363,7 @@ static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb)if (le16_to_cpu (data->magic) ==MTDSWAP_MAGIC_CLEAN ) { eb->erase_count =le32_to_cpu (data->count); -if (ret == -EUCLEAN ) +if (mtd_is_bitflip (ret)) ret =MTDSWAP_SCANNED_BITFLIP ;else {if (le16_to_cpu (data2->magic) ==MTDSWAP_MAGIC_DIRTY )
@@ -408,7 +408,7 @@ static int mtdswap_write_marker(struct mtdswap_dev *d, struct swap_eb *eb,if (ret) {dev_warn (d->dev,"Write OOB failed for block at %08llx " "error %d\n" , offset, ret); -if (ret == -EIO || ret == -EBADMSG ) +if (ret == -EIO ||mtd_is_eccerr (ret))mtdswap_handle_write_error (d, eb);return ret; }
@@ -628,7 +628,7 @@ static int mtdswap_map_free_block(struct mtdswap_dev *d, unsigned int page,TREE_COUNT (d,CLEAN )--; ret =mtdswap_write_marker (d, eb,MTDSWAP_TYPE_DIRTY ); - }while (ret == -EIO || ret == -EBADMSG ); + }while (ret == -EIO ||mtd_is_eccerr (ret));if (ret)return ret;
@@ -678,7 +678,7 @@ retry: ret =mtdswap_map_free_block (d, page, bp); eb = d->eb_data + (*bp / d->pages_per_eblk); -if (ret == -EIO || ret == -EBADMSG ) { +if (ret == -EIO ||mtd_is_eccerr (ret)) { d->curr_write =NULL ; eb->active_count--; d->revmap[*bp] =PAGE_UNDEF ;
@@ -690,7 +690,7 @@ retry: writepos = (loff_t)*bp <<PAGE_SHIFT ; ret = mtd->write (mtd, writepos,PAGE_SIZE , &retlen, buf); -if (ret == -EIO || ret == -EBADMSG ) { +if (ret == -EIO ||mtd_is_eccerr (ret)) { d->curr_write_pos--; eb->active_count--; d->revmap[*bp] =PAGE_UNDEF ;
@@ -738,7 +738,7 @@ static int mtdswap_move_block(struct mtdswap_dev *d, unsigned int oldblock, retry: ret = mtd->read (mtd, readpos,PAGE_SIZE , &retlen, d->page_buf); -if (ret <0 && ret != -EUCLEAN ) { +if (ret <0 && !mtd_is_bitflip (ret)) { oldeb = d->eb_data + oldblock / d->pages_per_eblk; oldeb->flags |=EBLOCK_READERR ;
@@ -1016,7 +1016,7 @@ static int mtdswap_gc(struct mtdswap_dev *d, unsigned int background)if (ret ==0 )mtdswap_rb_add (d, eb,MTDSWAP_CLEAN ); -else if (ret != -EIO && ret != -EBADMSG ) +else if (ret != -EIO && !mtd_is_eccerr (ret))mtdswap_rb_add (d, eb,MTDSWAP_DIRTY );return 0 ;
@@ -1164,7 +1164,7 @@ retry: ret = mtd->read (mtd, readpos,PAGE_SIZE , &retlen, buf); d->mtd_read_count++; -if (ret == -EUCLEAN ) { +if (mtd_is_bitflip (ret)) { eb->flags |=EBLOCK_BITFLIP ;mtdswap_rb_add (d, eb,MTDSWAP_BITFLIP ); ret =0 ;
drivers/mtd/nand/diskonchip.c +1 -1
@@ -1031,7 +1031,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,WriteDOC (DOC_ECC_DIS , docptr, Mplus_ECCConf); elseWriteDOC (DOC_ECC_DIS ,docptr ,ECCConf ); -if (no_ecc_failures && (ret == -EBADMSG )) { +if (no_ecc_failures &&mtd_is_eccerr (ret)) {printk (KERN_ERR "suppressing ECC failure\n" ); ret =0 ; }
drivers/mtd/nand/nand_bbt.c +2 -2
@@ -400,7 +400,7 @@ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, ret =scan_read_raw_oob (mtd, buf, offs, readlen);/* Ignore ECC errors when checking for BBM */ -if (ret && ret != -EUCLEAN && ret != -EBADMSG ) +if (ret && !mtd_is_bitflip_or_eccerr (ret))return ret;for (j =0 ; j < len; j++, buf += scanlen) {
@@ -430,7 +430,7 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,*/ ret = mtd->read_oob (mtd, offs, &ops);/* Ignore ECC errors when checking for BBM */ -if (ret && ret != -EUCLEAN && ret != -EBADMSG ) +if (ret && !mtd_is_bitflip_or_eccerr (ret))return ret;if (check_short_pattern (buf, bd))
drivers/mtd/nftlcore.c +2 -2
@@ -425,7 +425,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p ret = mtd->read (mtd, (nftl->EraseSize * BlockMap[block]) + (block *512 ),512 , &retlen, movebuf); -if (ret <0 && ret != -EUCLEAN ) { +if (ret <0 && !mtd_is_bitflip (ret)) { ret = mtd->read (mtd, (nftl->EraseSize * BlockMap[block]) + (block *512 ),512 , &retlen, movebuf);
@@ -773,7 +773,7 @@ static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,size_t retlen;int res = mtd->read (mtd, ptr,512 , &retlen, buffer); -if (res <0 && res != -EUCLEAN ) +if (res <0 && !mtd_is_bitflip (res))return -EIO ; }return 0 ;
drivers/mtd/onenand/onenand_base.c +5 -5
@@ -1079,7 +1079,7 @@ static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int status)return status;/* check if we failed due to uncorrectable error */ -if (status != -EBADMSG && status !=ONENAND_BBT_READ_ECC_ERROR ) +if (!mtd_is_eccerr (status) && status !=ONENAND_BBT_READ_ECC_ERROR )return status;/* check if address lies in MLC region */
@@ -1159,7 +1159,7 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from,if (unlikely (ret)) ret =onenand_recover_lsb (mtd, from, ret);onenand_update_bufferram (mtd, from, !ret); -if (ret == -EBADMSG ) +if (mtd_is_eccerr (ret)) ret =0 ;if (ret)break ;
@@ -1255,7 +1255,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, this->command (mtd,ONENAND_CMD_READ , from, writesize); ret = this->wait (mtd,FL_READING );onenand_update_bufferram (mtd, from, !ret); -if (ret == -EBADMSG ) +if (mtd_is_eccerr (ret)) ret =0 ; } }
@@ -1315,7 +1315,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,/* Now wait for load */ ret = this->wait (mtd,FL_READING );onenand_update_bufferram (mtd, from, !ret); -if (ret == -EBADMSG ) +if (mtd_is_eccerr (ret)) ret =0 ; }
@@ -1403,7 +1403,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,if (unlikely (ret)) ret =onenand_recover_lsb (mtd, from, ret); -if (ret && ret != -EBADMSG ) { +if (ret && !mtd_is_eccerr (ret)) {printk (KERN_ERR "%s: read failed = 0x%x\n" , __func__, ret);break ;
drivers/mtd/sm_ftl.c +2 -2
@@ -281,7 +281,7 @@ again: ret = mtd->read_oob (mtd,sm_mkoffset (ftl, zone, block, boffset), &ops);/* Test for unknown errors */ -if (ret !=0 && ret != -EUCLEAN && ret != -EBADMSG ) { +if (ret !=0 && !mtd_is_bitflip_or_eccerr (ret)) {dbg ("read of block %d at zone %d, failed due to error (%d)" , block, zone, ret); goto again;
@@ -306,7 +306,7 @@ again: }/* Test ECC*/ -if (ret == -EBADMSG || +if (mtd_is_eccerr (ret) || (ftl->smallpagenand &&sm_correct_sector (buffer, oob))) { dbg("read of block %d at zone %d, failed due to ECC error",
drivers/mtd/tests/mtd_pagetest.c +14 -14
@@ -128,7 +128,7 @@ static int verify_eraseblock(int ebnum)for (j =0 ; j < pgcnt -1 ; ++j, addr += pgsize) {/* Do a read to set the internal dataRAMs to different data */ err = mtd->read (mtd, addr0, bufsize, &read, twopages); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != bufsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -136,7 +136,7 @@ static int verify_eraseblock(int ebnum)return err; } err = mtd->read (mtd, addrn - bufsize, bufsize, &read, twopages); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != bufsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -146,7 +146,7 @@ static int verify_eraseblock(int ebnum)memset (twopages,0 , bufsize); read =0 ; err = mtd->read (mtd, addr, bufsize, &read, twopages); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != bufsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -164,7 +164,7 @@ static int verify_eraseblock(int ebnum)unsigned long oldnext = next;/* Do a read to set the internal dataRAMs to different data */ err = mtd->read (mtd, addr0, bufsize, &read, twopages); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != bufsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -172,7 +172,7 @@ static int verify_eraseblock(int ebnum)return err; } err = mtd->read (mtd, addrn - bufsize, bufsize, &read, twopages); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != bufsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -182,7 +182,7 @@ static int verify_eraseblock(int ebnum)memset (twopages,0 , bufsize); read =0 ; err = mtd->read (mtd, addr, bufsize, &read, twopages); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != bufsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -231,7 +231,7 @@ static int crosstest(void) read =0 ; addr = addrn - pgsize - pgsize; err = mtd->read (mtd, addr, pgsize, &read, pp1); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -244,7 +244,7 @@ static int crosstest(void) read =0 ; addr = addrn - pgsize - pgsize - pgsize; err = mtd->read (mtd, addr, pgsize, &read, pp1); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -258,7 +258,7 @@ static int crosstest(void) addr = addr0;printk (PRINT_PREF "reading page at %#llx\n" , (long long )addr); err = mtd->read (mtd, addr, pgsize, &read, pp2); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -272,7 +272,7 @@ static int crosstest(void) addr = addrn - pgsize;printk (PRINT_PREF "reading page at %#llx\n" , (long long )addr); err = mtd->read (mtd, addr, pgsize, &read, pp3); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -286,7 +286,7 @@ static int crosstest(void) addr = addr0;printk (PRINT_PREF "reading page at %#llx\n" , (long long )addr); err = mtd->read (mtd, addr, pgsize, &read, pp4); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -345,7 +345,7 @@ static int erasecrosstest(void)printk (PRINT_PREF "reading 1st page of block %d\n" , ebnum);memset (readbuf,0 , pgsize); err = mtd->read (mtd, addr0, pgsize, &read, readbuf); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -383,7 +383,7 @@ static int erasecrosstest(void)printk (PRINT_PREF "reading 1st page of block %d\n" , ebnum);memset (readbuf,0 , pgsize); err = mtd->read (mtd, addr0, pgsize, &read, readbuf); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -439,7 +439,7 @@ static int erasetest(void)printk (PRINT_PREF "reading 1st page of block %d\n" , ebnum); err = mtd->read (mtd, addr0, pgsize, &read, twopages); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
drivers/mtd/tests/mtd_readtest.c +1 -1
@@ -75,7 +75,7 @@ static int read_eraseblock_by_page(int ebnum) ops.datbuf =NULL ; ops.oobbuf = oobbuf; ret = mtd->read_oob (mtd, addr, &ops); -if ((ret && ret != -EUCLEAN ) || +if ((ret && !mtd_is_bitflip (ret)) || ops.oobretlen != mtd->oobsize) {printk (PRINT_PREF "error: read oob failed at " "%#llx\n" , (long long )addr);
drivers/mtd/tests/mtd_speedtest.c +4 -4
@@ -216,7 +216,7 @@ static int read_eraseblock(int ebnum) err = mtd->read (mtd, addr, mtd->erasesize, &read, iobuf);/* Ignore corrected ECC errors */ -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != mtd->erasesize) {printk (PRINT_PREF "error: read failed at %#llx\n" , addr);
@@ -237,7 +237,7 @@ static int read_eraseblock_by_page(int ebnum)for (i =0 ; i < pgcnt; i++) { err = mtd->read (mtd, addr, pgsize, &read, buf);/* Ignore corrected ECC errors */ -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -263,7 +263,7 @@ static int read_eraseblock_by_2pages(int ebnum)for (i =0 ; i < n; i++) { err = mtd->read (mtd, addr, sz, &read, buf);/* Ignore corrected ECC errors */ -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != sz) { printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -278,7 +278,7 @@ static int read_eraseblock_by_2pages(int ebnum)if (pgcnt %2 ) { err = mtd->read (mtd, addr, pgsize, &read, buf);/* Ignore corrected ECC errors */ -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n",
drivers/mtd/tests/mtd_stresstest.c +1 -1
@@ -154,7 +154,7 @@ static int do_read(void) } addr = eb * mtd->erasesize + offs; err = mtd->read (mtd, addr, len, &read, readbuf); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err)) err =0 ;if (unlikely (err || read != len)) { printk(PRINT_PREF "error: read failed at 0x%llx\n",
drivers/mtd/tests/mtd_subpagetest.c +4 -4
@@ -198,7 +198,7 @@ static int verify_eraseblock(int ebnum) read =0 ; err = mtd->read (mtd, addr, subpgsize, &read, readbuf);if (unlikely (err || read != subpgsize)) { -if (err == -EUCLEAN && read == subpgsize) { +if (mtd_is_bitflip (err) && read == subpgsize) {printk (PRINT_PREF "ECC correction at %#llx\n" , (long long )addr); err =0 ;
@@ -226,7 +226,7 @@ static int verify_eraseblock(int ebnum) read =0 ; err = mtd->read (mtd, addr, subpgsize, &read, readbuf);if (unlikely (err || read != subpgsize)) { -if (err == -EUCLEAN && read == subpgsize) { +if (mtd_is_bitflip (err) && read == subpgsize) {printk (PRINT_PREF "ECC correction at %#llx\n" , (long long )addr); err =0 ;
@@ -264,7 +264,7 @@ static int verify_eraseblock2(int ebnum) read =0 ; err = mtd->read (mtd, addr, subpgsize * k, &read, readbuf);if (unlikely (err || read != subpgsize * k)) { -if (err == -EUCLEAN && read == subpgsize * k) { +if (mtd_is_bitflip (err) && read == subpgsize * k) {printk (PRINT_PREF "ECC correction at %#llx\n" , (long long )addr); err =0 ;
@@ -298,7 +298,7 @@ static int verify_eraseblock_ff(int ebnum) read =0 ; err = mtd->read (mtd, addr, subpgsize, &read, readbuf);if (unlikely (err || read != subpgsize)) { -if (err == -EUCLEAN && read == subpgsize) { +if (mtd_is_bitflip (err) && read == subpgsize) {printk (PRINT_PREF "ECC correction at %#llx\n" , (long long )addr); err =0 ;
drivers/mtd/tests/mtd_torturetest.c +1 -1
@@ -138,7 +138,7 @@ static inline int check_eraseblock(int ebnum, unsigned char *buf) retry: err = mtd->read (mtd, addr, len, &read, check_buf); -if (err == -EUCLEAN ) +if (mtd_is_bitflip (err))printk (PRINT_PREF "single bit flip occurred at EB %d " "MTD reported that it was fixed.\n" , ebnum);else if (err) {
drivers/mtd/ubi/eba.c +1 -1
@@ -443,7 +443,7 @@ retry:if (err ==UBI_IO_BITFLIPS ) { scrub =1 ; err =0 ; - }else if (err == -EBADMSG ) { + }else if (mtd_is_eccerr (err)) {if (vol->vol_type ==UBI_DYNAMIC_VOLUME ) goto out_unlock; scrub =1 ;
drivers/mtd/ubi/io.c +12 -12
@@ -172,9 +172,9 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, retry: err = ubi->mtd->read (ubi->mtd, addr, len, &read, buf);if (err) { -const char *errstr = (err == -EBADMSG ) ?" (ECC error)" :"" ; +const char *errstr =mtd_is_eccerr (err) ?" (ECC error)" :"" ; -if (err == -EUCLEAN ) { +if (mtd_is_bitflip (err)) {/* * -EUCLEAN is reported if there was a bit-flip which * was corrected, so this is harmless.
@@ -205,7 +205,7 @@ retry:* all the requested data. But some buggy drivers might do * this, so we change it to -EIO. */ -if (read != len && err == -EBADMSG ) { +if (read != len &&mtd_is_eccerr (err)) {ubi_assert (0 ); err = -EIO ; }
@@ -469,7 +469,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum) out:mutex_unlock (&ubi->buf_mutex); -if (err ==UBI_IO_BITFLIPS || err == -EBADMSG ) { +if (err ==UBI_IO_BITFLIPS ||mtd_is_eccerr (err)) {/* * If a bit-flip or data integrity error was detected, the test * has not passed because it happened on a freshly erased
@@ -760,7 +760,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, read_err =ubi_io_read (ubi, ec_hdr, pnum,0 ,UBI_EC_HDR_SIZE );if (read_err) { -if (read_err !=UBI_IO_BITFLIPS && read_err != -EBADMSG ) +if (read_err !=UBI_IO_BITFLIPS && !mtd_is_eccerr (read_err))return read_err;/*
@@ -776,7 +776,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, magic =be32_to_cpu (ec_hdr->magic);if (magic !=UBI_EC_HDR_MAGIC ) { -if (read_err == -EBADMSG ) +if (mtd_is_eccerr (read_err))return UBI_IO_BAD_HDR_EBADMSG ;/*
@@ -1032,12 +1032,12 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, p = (char *)vid_hdr - ubi->vid_hdr_shift; read_err =ubi_io_read (ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); -if (read_err && read_err !=UBI_IO_BITFLIPS && read_err != -EBADMSG ) +if (read_err && read_err !=UBI_IO_BITFLIPS && !mtd_is_eccerr (read_err))return read_err; magic =be32_to_cpu (vid_hdr->magic);if (magic !=UBI_VID_HDR_MAGIC ) { -if (read_err == -EBADMSG ) +if (mtd_is_eccerr (read_err))return UBI_IO_BAD_HDR_EBADMSG ;if (ubi_check_pattern (vid_hdr,0xFF ,UBI_VID_HDR_SIZE )) {
@@ -1219,7 +1219,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)return -ENOMEM ; err =ubi_io_read (ubi, ec_hdr, pnum,0 ,UBI_EC_HDR_SIZE ); -if (err && err !=UBI_IO_BITFLIPS && err != -EBADMSG ) +if (err && err !=UBI_IO_BITFLIPS && !mtd_is_eccerr (err)) goto exit; crc =crc32 (UBI_CRC32_INIT , ec_hdr,UBI_EC_HDR_SIZE_CRC );
@@ -1306,7 +1306,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) p = (char *)vid_hdr - ubi->vid_hdr_shift; err =ubi_io_read (ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); -if (err && err !=UBI_IO_BITFLIPS && err != -EBADMSG ) +if (err && err !=UBI_IO_BITFLIPS && !mtd_is_eccerr (err)) goto exit; crc =crc32 (UBI_CRC32_INIT , vid_hdr,UBI_EC_HDR_SIZE_CRC );
@@ -1358,7 +1358,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, } err = ubi->mtd->read (ubi->mtd, addr, len, &read, buf1); -if (err && err != -EUCLEAN ) +if (err && !mtd_is_bitflip (err)) goto out_free;for (i =0 ; i < len; i++) {
@@ -1422,7 +1422,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) } err = ubi->mtd->read (ubi->mtd, addr, len, &read, buf); -if (err && err != -EUCLEAN ) { +if (err && !mtd_is_bitflip (err)) {ubi_err ("error %d while reading %d bytes from PEB %d:%d, " "read %zd bytes" , err, len, pnum, offset, read); goto error;
drivers/mtd/ubi/kapi.c +1 -1
@@ -410,7 +410,7 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,return 0 ; err =ubi_eba_read_leb (ubi, vol, lnum, buf, offset, len, check); -if (err && err == -EBADMSG && vol->vol_type ==UBI_STATIC_VOLUME ) { +if (err &&mtd_is_eccerr (err) && vol->vol_type ==UBI_STATIC_VOLUME ) {ubi_warn ("mark volume %d as corrupted" , vol_id); vol->corrupted =1 ; }
drivers/mtd/ubi/misc.c +1 -1
@@ -81,7 +81,7 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id) err =ubi_eba_read_leb (ubi, vol, i, buf,0 , size,1 );if (err) { -if (err == -EBADMSG ) +if (mtd_is_eccerr (err)) err =1 ;break ; }
drivers/mtd/ubi/scan.c +2 -2
@@ -395,7 +395,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, } err =ubi_io_read_data (ubi, buf, pnum,0 , len); -if (err && err !=UBI_IO_BITFLIPS && err != -EBADMSG ) +if (err && err !=UBI_IO_BITFLIPS && !mtd_is_eccerr (err)) goto out_free_buf; data_crc =be32_to_cpu (vid_hdr->data_crc);
@@ -793,7 +793,7 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr, err =ubi_io_read (ubi, ubi->peb_buf1, pnum, ubi->leb_start, ubi->leb_size); -if (err ==UBI_IO_BITFLIPS || err == -EBADMSG ) { +if (err ==UBI_IO_BITFLIPS ||mtd_is_eccerr (err)) {/* * Bit-flips or integrity errors while reading the data area. * It is difficult to say for sure what type of corruption is
drivers/mtd/ubi/vtbl.c +1 -1
@@ -423,7 +423,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, err =ubi_io_read_data (ubi, leb[seb->lnum], seb->pnum,0 , ubi->vtbl_size); -if (err ==UBI_IO_BITFLIPS || err == -EBADMSG ) +if (err ==UBI_IO_BITFLIPS ||mtd_is_eccerr (err))/* * Scrub the PEB later. Note, -EBADMSG indicates an * uncorrectable ECC error, but we have our own CRC and
Signature · 1 line
1.7.5.4
PATCH 5/14 mtd: nand: remove unnecessary variable
In reply to Brian Norriswriteops' is unnecessary in the function nand_update_bbt()'
--- drivers/mtd/nand/nand_bbt.c | 8 +++----- 1 files changed, 3 insertions(+), 5 deletions(-)
drivers/mtd/nand/nand_bbt.c +3 -5
@@ -1171,7 +1171,7 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)int nand_update_bbt (struct mtd_info *mtd,loff_t offs) {struct nand_chip *this = mtd->priv; -int len, res =0 , writeops =0 ; +int len, res =0 ;int chip, chipsel;uint8_t *buf;struct nand_bbt_descr *td = this->bbt_td;
@@ -1187,8 +1187,6 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)if (!buf)return -ENOMEM ; - writeops = md !=NULL ?0x03 :0x01 ; -/* Do we have a bbt per chip? */ if (td->options &NAND_BBT_PERCHIP ) { chip = (int )(offs >> this->chip_shift);
@@ -1203,13 +1201,13 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs) md->version[chip]++;/* Write the bad block table to the device? */ -if ((writeops &0x01 ) && (td->options &NAND_BBT_WRITE )) { +if (td->options &NAND_BBT_WRITE ) { res =write_bbt (mtd, buf, td, md, chipsel);if (res <0 ) goto out; }/* Write the mirror bad block table to the device? */ -if ((writeops &0x02 ) && md && (md->options &NAND_BBT_WRITE )) { +if (md && (md->options &NAND_BBT_WRITE )) { res =write_bbt (mtd, buf, md, td, chipsel); }
Signature · 1 line
1.7.5.4
Artem Bityutskiy
AppliedRe: [PATCH 05/14] mtd: nand: remove unnecessary variable
Quoted 3 lines · Brian Norris
writeops' is unnecessary in the functionnand_update_bbt()'Signed-off-by Brian Norris <[email protected]>
Pushed to my tree, thanks!
Signature · 2 lines
Best Regards, Artem Bityutskiy
PATCH 6/14 mtd: nand: fix style
In reply to Brian NorrisRemove some extra spaces
Consistently use '0x' prefix for bitfield-like constants
Spelling: "aplies" -> "applies"
--- drivers/mtd/nand/nand_bbt.c | 28 ++++++++++++++-------------- 1 files changed, 14 insertions(+), 14 deletions(-)
drivers/mtd/nand/nand_bbt.c +14 -14
@@ -183,16 +183,16 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,size_t retlen, len, totlen;loff_t from;int bits = td->options &NAND_BBT_NRBITS_MSK ; -uint8_t msk = (uint8_t ) ((1 << bits) -1 ); +uint8_t msk = (uint8_t )((1 << bits) -1 );u32 marker_len;int reserved_block_code = td->reserved_block_code; totlen = (num * bits) >>3 ; marker_len =add_marker_len (td); - from = ((loff_t ) page) << this->page_shift; + from = ((loff_t )page) << this->page_shift;while (totlen) { - len =min (totlen, (size_t ) (1 << this->bbt_erase_shift)); + len =min (totlen, (size_t )(1 << this->bbt_erase_shift));if (marker_len) {/* * In case the BBT marker is not in the OOB area it
@@ -250,7 +250,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,* @mtd: MTD device structure * @buf: temporary buffer * @td: descriptor for the bad block table -* @chip: read the table for a specific chip, -1 read all chips; aplies only if +* @chip: read the table for a specific chip, -1 read all chips; applies only if * NAND_BBT_PERCHIP option is set * * Read the bad block table for all chips starting at a given page. We assume
@@ -743,12 +743,12 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, bbtoffs = chip * (numblocks >>2 ); - to = ((loff_t ) page) << this->page_shift; + to = ((loff_t )page) << this->page_shift;/* Must we save the block contents? */ if (td->options &NAND_BBT_SAVECONTENT ) {/* Make it block aligned */ - to &= ~((loff_t) ((1 << this->bbt_erase_shift) -1 )); + to &= ~((loff_t)((1 << this->bbt_erase_shift) -1 )); len =1 << this->bbt_erase_shift; res = mtd->read (mtd, to, len, &retlen, buf);if (res <0 ) {
@@ -771,7 +771,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, pageoffs = page - (int )(to >> this->page_shift); offs = pageoffs << this->page_shift;/* Preset the bbt area with 0xff */ -memset (&buf[offs],0xff , (size_t ) (numblocks >> sft)); +memset (&buf[offs],0xff , (size_t )(numblocks >> sft)); ooboffs = len + (pageoffs * mtd->oobsize); }else if (td->options &NAND_BBT_NO_OOB ) {
@@ -781,7 +781,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,if (td->options &NAND_BBT_VERSION ) offs++;/* Calc length */ - len = (size_t ) (numblocks >> sft); + len = (size_t )(numblocks >> sft); len += offs;/* Make it page aligned! */ len =ALIGN (len, mtd->writesize);
@@ -791,7 +791,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,memcpy (buf, td->pattern, td->len); }else {/* Calc length */ - len = (size_t ) (numblocks >> sft); + len = (size_t )(numblocks >> sft);/* Make it page aligned! */ len =ALIGN (len, mtd->writesize);/* Preset the buffer with 0xff */
@@ -903,14 +903,14 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descif (td->pages[i] ==-1 ) { rd = md; td->version[i] = md->version[i]; - writeops =1 ; + writeops =0x01 ; goto writecheck; }if (md->pages[i] ==-1 ) { rd = td; md->version[i] = td->version[i]; - writeops =2 ; + writeops =0x02 ; goto writecheck; }
@@ -921,14 +921,14 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc goto writecheck; } -if (((int8_t ) (td->version[i] - md->version[i])) >0 ) { +if (((int8_t )(td->version[i] - md->version[i])) >0 ) { rd = td; md->version[i] = td->version[i]; - writeops =2 ; + writeops =0x02 ; }else { rd = md; td->version[i] = md->version[i]; - writeops =1 ; + writeops =0x01 ; } goto writecheck;
Signature · 1 line
1.7.5.4
Re: [PATCH 06/14] mtd: nand: fix style
Quoted 5 lines · Brian Norris
Remove some extra spaces
Consistently use '0x' prefix for bitfield-like constants
Spelling: "aplies" -> "applies"Signed-off-by Brian Norris <[email protected]>
Pushed this one to my tree as well, thanks!
Signature · 2 lines
Best Regards, Artem Bityutskiy
PATCH 7/14 mtd: nand: begin restructuring check_create
In reply to Brian NorrisWe will begin restructuring the code for check_create so that we can make some important changes. For now, we should just begin to get rid of some goto statements to make things cleaner. This is the first step of a few, which are separated to make them easier to follow.
This step should just be a code refactor.
--- drivers/mtd/nand/nand_bbt.c | 24 +++++------------------- 1 files changed, 5 insertions(+), 19 deletions(-)
drivers/mtd/nand/nand_bbt.c +5 -19
@@ -898,30 +898,19 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descif (td->pages[i] ==-1 && md->pages[i] ==-1 ) { writeops =0x03 ; goto create; - } - -if (td->pages[i] ==-1 ) { + }else if (td->pages[i] ==-1 ) { rd = md; td->version[i] = md->version[i]; writeops =0x01 ; - goto writecheck; - } - -if (md->pages[i] ==-1 ) { + }else if (md->pages[i] ==-1 ) { rd = td; md->version[i] = td->version[i]; writeops =0x02 ; - goto writecheck; - } - -if (td->version[i] == md->version[i]) { + }else if (td->version[i] == md->version[i]) { rd = td;if (!(td->options &NAND_BBT_VERSION )) rd2 = md; - goto writecheck; - } - -if (((int8_t )(td->version[i] - md->version[i])) >0 ) { + }else if (((int8_t )(td->version[i] - md->version[i])) >0 ) { rd = td; md->version[i] = td->version[i]; writeops =0x02 ;
@@ -930,17 +919,14 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc td->version[i] = md->version[i]; writeops =0x01 ; } - - goto writecheck; - }else {if (td->pages[i] ==-1 ) { writeops =0x01 ; goto create; } rd = td; - goto writecheck; } + goto writecheck; create:/* Create the bad block table by scanning the device? */ if (!(td->options &NAND_BBT_CREATE ))
Signature · 1 line
1.7.5.4
PATCH 8/14 mtd: nand: remove gotos in `check_create()'
In reply to Brian NorrisThis is a second step in restructuring `check_create()'. When we don't rely on goto statements for our main functionality, the code will become a little easier to manipulate.
--- drivers/mtd/nand/nand_bbt.c | 39 +++++++++++++++++++++------------------ 1 files changed, 21 insertions(+), 18 deletions(-)
drivers/mtd/nand/nand_bbt.c +19 -16
@@ -875,7 +875,7 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b*/ static int check_create (struct mtd_info *mtd,uint8_t *buf,struct nand_bbt_descr *bd) { -int i, chips, writeops, chipsel, res; +int i, chips, writeops, create, chipsel, res;struct nand_chip *this = mtd->priv;struct nand_bbt_descr *td = this->bbt_td;struct nand_bbt_descr *md = this->bbt_md;
@@ -889,6 +889,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descfor (i =0 ; i < chips; i++) { writeops =0 ; + create =0 ; rd =NULL ; rd2 =NULL ;/* Per chip or per device? */
@@ -896,8 +897,8 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc/* Mirrored table available? */ if (md) {if (td->pages[i] ==-1 && md->pages[i] ==-1 ) { + create =1 ; writeops =0x03 ; - goto create; }else if (td->pages[i] ==-1 ) { rd = md; td->version[i] = md->version[i];
@@ -921,25 +922,27 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc } }else {if (td->pages[i] ==-1 ) { + create =1 ; writeops =0x01 ; - goto create; + }else { + rd = td; } - rd = td; } - goto writecheck; - create: -/* Create the bad block table by scanning the device? */ -if (!(td->options &NAND_BBT_CREATE )) -continue ; -/* Create the table in memory by scanning the chip(s) */ -if (!(this->bbt_options &NAND_BBT_CREATE_EMPTY )) -create_bbt (mtd, buf, bd, chipsel); +if (create) { +/* Create the bad block table by scanning the device? */ +if (!(td->options &NAND_BBT_CREATE )) +continue ; + +/* Create the table in memory by scanning the chip(s) */ +if (!(this->bbt_options &NAND_BBT_CREATE_EMPTY )) +create_bbt (mtd, buf, bd, chipsel); + + td->version[i] =1 ; +if (md) + md->version[i] =1 ; + } - td->version[i] =1 ; -if (md) - md->version[i] =1 ; - writecheck:/* Read back first? */ if (rd)read_abs_bbt (mtd, buf, rd, chipsel);
Signature · 1 line
1.7.5.4
PATCH 9/14 mtd: nand: report ECC errors properly when reading BBT
In reply to Brian NorrisInstead of just printing a warning when encountering ECC errors, we should return a proper error status and print a more informative warning. Later, we will handle these error messages in the upper layers of the BBT scan.
Note that this patch makes our check for ECC error codes a little bit more restrictive, leaving all unrecognized errors to the generic "else" clause. This shouldn't cause problems and could even be a benefit.
This code is based on some findings reported by Matthieu Castet.
--- drivers/mtd/nand/nand_bbt.c | 17 ++++++++++++----- 1 files changed, 12 insertions(+), 5 deletions(-)
drivers/mtd/nand/nand_bbt.c +12 -5
@@ -178,7 +178,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td)static int read_bbt (struct mtd_info *mtd,uint8_t *buf,int page,int num,struct nand_bbt_descr *td,int offs) { -int res, i, j, act =0 ; +int res, ret =0 , i, j, act =0 ;struct nand_chip *this = mtd->priv;size_t retlen, len, totlen;loff_t from;
@@ -204,11 +204,18 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, } res = mtd->read (mtd, from, len, &retlen, buf);if (res <0 ) { -if (retlen != len) { -pr_info ("nand_bbt: error reading bad block table\n" ); +if (is_uncorrected_ecc_error (res)) { +pr_info ("nand_bbt: ECC error in BBT at " +"0x%012llx\n" , from & ~mtd->writesize); +return res; + }else if (is_corrected_ecc_error (res)) { +pr_info ("nand_bbt: corrected error in BBT at " +"0x%012llx\n" , from & ~mtd->writesize); + ret = res; + }else { +pr_info ("nand_bbt: error reading BBT\n" );return res; } -pr_warn ("nand_bbt: ECC error while reading bad block table\n" ); }/* Analyse data */
@@ -242,7 +249,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, totlen -= len; from += len; } -return 0 ; +return ret; }/**
Signature · 1 line
1.7.5.4
PATCH v2 9/14 mtd: nand: report ECC errors properly when reading BBT
Instead of just printing a warning when encountering ECC errors, we should return a proper error status and print a more informative warning. Later, we will handle these error messages in the upper layers of the BBT scan.
Note that this patch makes our check for ECC error codes a little bit more restrictive, leaving all unrecognized errors to the generic "else" clause. This shouldn't cause problems and could even be a benefit.
This code is based on some findings reported by Matthieu Castet.
---
v2: change to `mtd_is_*' prefix
drivers/mtd/nand/nand_bbt.c | 17 ++++++++++++----- 1 files changed, 12 insertions(+), 5 deletions(-)
drivers/mtd/nand/nand_bbt.c +12 -5
@@ -178,7 +178,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td)static int read_bbt (struct mtd_info *mtd,uint8_t *buf,int page,int num,struct nand_bbt_descr *td,int offs) { -int res, i, j, act =0 ; +int res, ret =0 , i, j, act =0 ;struct nand_chip *this = mtd->priv;size_t retlen, len, totlen;loff_t from;
@@ -204,11 +204,18 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, } res = mtd->read (mtd, from, len, &retlen, buf);if (res <0 ) { -if (retlen != len) { -pr_info ("nand_bbt: error reading bad block table\n" ); +if (mtd_is_eccerr (res)) { +pr_info ("nand_bbt: ECC error in BBT at " +"0x%012llx\n" , from & ~mtd->writesize); +return res; + }else if (mtd_is_bitflip (res)) { +pr_info ("nand_bbt: corrected error in BBT at " +"0x%012llx\n" , from & ~mtd->writesize); + ret = res; + }else { +pr_info ("nand_bbt: error reading BBT\n" );return res; } -pr_warn ("nand_bbt: ECC error while reading bad block table\n" ); }/* Analyse data */
@@ -242,7 +249,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, totlen -= len; from += len; } -return 0 ; +return ret; }/**
Signature · 1 line
1.7.5.4
PATCH 10/14 mtd: nand: scrub BBT on ECC errors
In reply to Brian NorrisNow that `read_bbt()' returns ECC error codes properly, we handle those codes when checking the integrity of our flash-based BBT.
The modifications can be described by this new policy:
*) On any uncorrected ECC error, we invalidate the corresponding table
and retry our version-checking integrity logic.
*) On corrected ECC errors, we mark both tables for re-writing to flash
(a.k.a. scrubbing).
Current integrity checks (i.e., comparing version numbers, etc.) should take care of all the cases that result in rescanning the device for bad blocks or falling back to the BBT as found in the mirror descriptor.
--- drivers/mtd/nand/nand_bbt.c | 29 ++++++++++++++++++++++++----- 1 files changed, 24 insertions(+), 5 deletions(-)
drivers/mtd/nand/nand_bbt.c +24 -5
@@ -882,7 +882,7 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b*/ static int check_create (struct mtd_info *mtd,uint8_t *buf,struct nand_bbt_descr *bd) { -int i, chips, writeops, create, chipsel, res; +int i, chips, writeops, create, chipsel, res, res2;struct nand_chip *this = mtd->priv;struct nand_bbt_descr *td = this->bbt_td;struct nand_bbt_descr *md = this->bbt_md;
@@ -899,6 +899,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc create =0 ; rd =NULL ; rd2 =NULL ; + res = res2 =0 ;/* Per chip or per device? */ chipsel = (td->options &NAND_BBT_PERCHIP ) ? i :-1 ;/* Mirrored table available? */
@@ -951,11 +952,29 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc }/* Read back first? */ -if (rd) -read_abs_bbt (mtd, buf, rd, chipsel); +if (rd) { + res =read_abs_bbt (mtd, buf, rd, chipsel); +if (is_uncorrected_ecc_error (res)) { +/* Mark table as invalid */ + rd->pages[i] =-1 ; + i--; +continue ; + } + }/* If they weren't versioned, read both */ -if (rd2) -read_abs_bbt (mtd, buf, rd2, chipsel); +if (rd2) { + res2 =read_abs_bbt (mtd, buf, rd2, chipsel); +if (is_uncorrected_ecc_error (res2)) { +/* Mark table as invalid */ + rd2->pages[i] =-1 ; + i--; +continue ; + } + } + +/* Scrub the flash table(s)? */ +if (is_corrected_ecc_error (res) ||is_corrected_ecc_error (res2)) + writeops =0x03 ;/* Write the bad block table to the device? */ if ((writeops &0x01 ) && (td->options &NAND_BBT_WRITE )) {
Signature · 1 line
1.7.5.4
PATCH v2 10/14 mtd: nand: scrub BBT on ECC errors
Now that `read_bbt()' returns ECC error codes properly, we handle those codes when checking the integrity of our flash-based BBT.
The modifications can be described by this new policy:
*) On any uncorrected ECC error, we invalidate the corresponding table
and retry our version-checking integrity logic.
*) On corrected bitflips, we mark both tables for re-writing to flash
(a.k.a. scrubbing).
Current integrity checks (i.e., comparing version numbers, etc.) should take care of all the cases that result in rescanning the device for bad blocks or falling back to the BBT as found in the mirror descriptor.
---
v2: change to `mtd_is_*' prefix
drivers/mtd/nand/nand_bbt.c | 29 ++++++++++++++++++++++++----- 1 files changed, 24 insertions(+), 5 deletions(-)
drivers/mtd/nand/nand_bbt.c +24 -5
@@ -882,7 +882,7 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b*/ static int check_create (struct mtd_info *mtd,uint8_t *buf,struct nand_bbt_descr *bd) { -int i, chips, writeops, create, chipsel, res; +int i, chips, writeops, create, chipsel, res, res2;struct nand_chip *this = mtd->priv;struct nand_bbt_descr *td = this->bbt_td;struct nand_bbt_descr *md = this->bbt_md;
@@ -899,6 +899,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc create =0 ; rd =NULL ; rd2 =NULL ; + res = res2 =0 ;/* Per chip or per device? */ chipsel = (td->options &NAND_BBT_PERCHIP ) ? i :-1 ;/* Mirrored table available? */
@@ -951,11 +952,29 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc }/* Read back first? */ -if (rd) -read_abs_bbt (mtd, buf, rd, chipsel); +if (rd) { + res =read_abs_bbt (mtd, buf, rd, chipsel); +if (mtd_is_eccerr (res)) { +/* Mark table as invalid */ + rd->pages[i] =-1 ; + i--; +continue ; + } + }/* If they weren't versioned, read both */ -if (rd2) -read_abs_bbt (mtd, buf, rd2, chipsel); +if (rd2) { + res2 =read_abs_bbt (mtd, buf, rd2, chipsel); +if (mtd_is_eccerr (res2)) { +/* Mark table as invalid */ + rd2->pages[i] =-1 ; + i--; +continue ; + } + } + +/* Scrub the flash table(s)? */ +if (mtd_is_bitflip (res) ||mtd_is_bitflip (res2)) + writeops =0x03 ;/* Write the bad block table to the device? */ if ((writeops &0x01 ) && (td->options &NAND_BBT_WRITE )) {
Signature · 1 line
1.7.5.4
PATCH 11/14 mtd: nand: wait to set BBT version
In reply to Brian NorrisBecause there are so many cases of checking, writing, and re-writing of the bad block table(s), we might as well wait until the we've settled on a valid, clean copy of the table. This also prevents us from falsely incrementing the table version. For example, we may have the following:
Primary table, with version 0x02
Mirror table, with version 0x01
Primary table has uncorrectable ECC errors
If we don't have this fix applied, then we will:
Choose to read the primary table (higher version) Set mirror table version to 0x02
Read back primary table
Invalidate table because of ECC errors
Retry readback operation with mirror table, now version 0x02 Mirrored table reads cleanly
Writeback BBT to primary table location (with "version 0x02")
However, the mirrored table shouldn't have a new version number. Instead, we actually want:
Choose to read the primary table (higher version) Read back primary table
Invalidate table because of ECC errors
Retry readback with mirror table (version 0x01) Mirrored table reads cleanly
Set both tables to version 0x01
Writeback BBT to primary table location (version 0x01)
--- drivers/mtd/nand/nand_bbt.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-)
drivers/mtd/nand/nand_bbt.c +8 -4
@@ -909,11 +909,9 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc writeops =0x03 ; }else if (td->pages[i] ==-1 ) { rd = md; - td->version[i] = md->version[i]; writeops =0x01 ; }else if (md->pages[i] ==-1 ) { rd = td; - md->version[i] = td->version[i]; writeops =0x02 ; }else if (td->version[i] == md->version[i]) { rd = td;
@@ -921,11 +919,9 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc rd2 = md; }else if (((int8_t )(td->version[i] - md->version[i])) >0 ) { rd = td; - md->version[i] = td->version[i]; writeops =0x02 ; }else { rd = md; - td->version[i] = md->version[i]; writeops =0x01 ; } }else {
@@ -957,6 +953,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descif (is_uncorrected_ecc_error (res)) {/* Mark table as invalid */ rd->pages[i] =-1 ; + rd->version[i] =0 ; i--;continue ; }
@@ -967,6 +964,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descif (is_uncorrected_ecc_error (res2)) {/* Mark table as invalid */ rd2->pages[i] =-1 ; + rd2->version[i] =0 ; i--;continue ; }
@@ -976,6 +974,12 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descif (is_corrected_ecc_error (res) ||is_corrected_ecc_error (res2)) writeops =0x03 ; +/* Update version numbers before writing */ +if (md) { + td->version[i] =max (td->version[i], md->version[i]); + md->version[i] = td->version[i]; + } +/* Write the bad block table to the device? */ if ((writeops &0x01 ) && (td->options &NAND_BBT_WRITE )) { res =write_bbt (mtd, buf, td, md, chipsel);
Signature · 1 line
1.7.5.4
PATCH v2 11/14 mtd: nand: wait to set BBT version
Because there are so many cases of checking, writing, and re-writing of the bad block table(s), we might as well wait until the we've settled on a valid, clean copy of the table. This also prevents us from falsely incrementing the table version. For example, we may have the following:
Primary table, with version 0x02
Mirror table, with version 0x01
Primary table has uncorrectable ECC errors
If we don't have this fix applied, then we will:
Choose to read the primary table (higher version) Set mirror table version to 0x02
Read back primary table
Invalidate table because of ECC errors
Retry readback operation with mirror table, now version 0x02 Mirrored table reads cleanly
Writeback BBT to primary table location (with "version 0x02")
However, the mirrored table shouldn't have a new version number. Instead, we actually want:
Choose to read the primary table (higher version) Read back primary table
Invalidate table because of ECC errors
Retry readback with mirror table (version 0x01) Mirrored table reads cleanly
Set both tables to version 0x01
Writeback BBT to primary table location (version 0x01)
---
v2: change to `mtd_is_*' prefix
drivers/mtd/nand/nand_bbt.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-)
drivers/mtd/nand/nand_bbt.c +8 -4
@@ -909,11 +909,9 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc writeops =0x03 ; }else if (td->pages[i] ==-1 ) { rd = md; - td->version[i] = md->version[i]; writeops =0x01 ; }else if (md->pages[i] ==-1 ) { rd = td; - md->version[i] = td->version[i]; writeops =0x02 ; }else if (td->version[i] == md->version[i]) { rd = td;
@@ -921,11 +919,9 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc rd2 = md; }else if (((int8_t )(td->version[i] - md->version[i])) >0 ) { rd = td; - md->version[i] = td->version[i]; writeops =0x02 ; }else { rd = md; - td->version[i] = md->version[i]; writeops =0x01 ; } }else {
@@ -957,6 +953,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descif (mtd_is_eccerr (res)) {/* Mark table as invalid */ rd->pages[i] =-1 ; + rd->version[i] =0 ; i--;continue ; }
@@ -967,6 +964,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descif (mtd_is_eccerr (res2)) {/* Mark table as invalid */ rd2->pages[i] =-1 ; + rd2->version[i] =0 ; i--;continue ; }
@@ -976,6 +974,12 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descif (mtd_is_bitflip (res) ||mtd_is_bitflip (res2)) writeops =0x03 ; +/* Update version numbers before writing */ +if (md) { + td->version[i] =max (td->version[i], md->version[i]); + md->version[i] = td->version[i]; + } +/* Write the bad block table to the device? */ if ((writeops &0x01 ) && (td->options &NAND_BBT_WRITE )) { res =write_bbt (mtd, buf, td, md, chipsel);
Signature · 1 line
1.7.5.4
PATCH 12/14 mtd: nand: do not scan bad blocks with NAND_BBT_NO_OOB set
In reply to Brian NorrisUpdates to our default function for creating bad block patterns have broken the "no OOB" feature. The NAND_BBT_NO_OOB option should not be set while scanning for bad blocks, but we've been passing all BBT options from nand_chip.bbt_options to the bad block scan. This causes us to hit the:
BUG_ON(bd->options & NAND_BBT_NO_OOB);
in create_bbt() when we scan the flash for bad blocks.
Thus, while it can be legal to set NAND_BBT_NO_OOB in a custom badblock pattern descriptor (presumably with NAND_BBT_CREATE disabled?), we should not pass it through in our default function.
Also, to help clarify and emphasize that the function creates bad block patterns only (not, for example, table descriptors for locating flash-based BBT), I renamed nand_create_default_bbt_descr' to nand_create_badblock_pattern'.
--- drivers/mtd/nand/nand_bbt.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-)
drivers/mtd/nand/nand_bbt.c +7 -6
@@ -1294,26 +1294,27 @@ static struct nand_bbt_descr bbt_mirror_no_bbt_descr = { .pattern = mirror_pattern }; +#define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB)/** -* nand_create_default_bbt_descr - [INTERN] Creates a BBT descriptor structure +* nand_create_badblock_pattern - [INTERN] Creates a BBT descriptor structure * @this: NAND chip to create descriptor for * * This function allocates and initializes a nand_bbt_descr for BBM detection -* based on the properties of "this". The new descriptor is stored in +* based on the properties of @this. The new descriptor is stored in * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when * passed to this function. */ -static int nand_create_default_bbt_descr (struct nand_chip *this) +static int nand_create_badblock_pattern (struct nand_chip *this) {struct nand_bbt_descr *bd;if (this->badblock_pattern) { -pr_warn ("BBT descr already allocated; not replacing\n" ); +pr_warn ("Bad block pattern already allocated; not replacing\n" );return -EINVAL ; } bd =kzalloc (sizeof (*bd),GFP_KERNEL );if (!bd)return -ENOMEM ; - bd->options = this->bbt_options; + bd->options = this->bbt_options &BADBLOCK_SCAN_MASK ; bd->offs = this->badblockpos; bd->len = (this->options &NAND_BUSWIDTH_16 ) ?2 :1 ; bd->pattern = scan_ff_pattern;
@@ -1367,7 +1368,7 @@ int nand_default_bbt(struct mtd_info *mtd) }if (!this->badblock_pattern) -nand_create_default_bbt_descr (this); +nand_create_badblock_pattern (this);return nand_scan_bbt (mtd, this->badblock_pattern); }
Signature · 1 line
1.7.5.4
PATCH v2 12/14 mtd: nand: do not scan bad blocks with NAND_BBT_NO_OOB set
Updates to our default function for creating bad block patterns have broken the "no OOB" feature. The NAND_BBT_NO_OOB option should not be set while scanning for bad blocks, but we've been passing all BBT options from nand_chip.bbt_options to the bad block scan. This causes us to hit the:
BUG_ON(bd->options & NAND_BBT_NO_OOB);
in create_bbt() when we scan the flash for bad blocks.
Thus, while it can be legal to set NAND_BBT_NO_OOB in a custom badblock pattern descriptor (presumably with NAND_BBT_CREATE disabled?), we should not pass it through in our default function.
Also, to help clarify and emphasize that the function creates bad block patterns only (not, for example, table descriptors for locating flash-based BBT), I renamed nand_create_default_bbt_descr' to nand_create_badblock_pattern'.
---
v2: change to `mtd_is_*' prefix
drivers/mtd/nand/nand_bbt.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-)
drivers/mtd/nand/nand_bbt.c +7 -6
@@ -1294,26 +1294,27 @@ static struct nand_bbt_descr bbt_mirror_no_bbt_descr = { .pattern = mirror_pattern }; +#define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB)/** -* nand_create_default_bbt_descr - [INTERN] Creates a BBT descriptor structure +* nand_create_badblock_pattern - [INTERN] Creates a BBT descriptor structure * @this: NAND chip to create descriptor for * * This function allocates and initializes a nand_bbt_descr for BBM detection -* based on the properties of "this". The new descriptor is stored in +* based on the properties of @this. The new descriptor is stored in * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when * passed to this function. */ -static int nand_create_default_bbt_descr (struct nand_chip *this) +static int nand_create_badblock_pattern (struct nand_chip *this) {struct nand_bbt_descr *bd;if (this->badblock_pattern) { -pr_warn ("BBT descr already allocated; not replacing\n" ); +pr_warn ("Bad block pattern already allocated; not replacing\n" );return -EINVAL ; } bd =kzalloc (sizeof (*bd),GFP_KERNEL );if (!bd)return -ENOMEM ; - bd->options = this->bbt_options; + bd->options = this->bbt_options &BADBLOCK_SCAN_MASK ; bd->offs = this->badblockpos; bd->len = (this->options &NAND_BUSWIDTH_16 ) ?2 :1 ; bd->pattern = scan_ff_pattern;
@@ -1367,7 +1368,7 @@ int nand_default_bbt(struct mtd_info *mtd) }if (!this->badblock_pattern) -nand_create_default_bbt_descr (this); +nand_create_badblock_pattern (this);return nand_scan_bbt (mtd, this->badblock_pattern); }
Signature · 1 line
1.7.5.4
PATCH 13/14 mtd: nand: invalidate cache on unaligned reads
In reply to Brian NorrisIn rare cases, we are given an unaligned parameter from' in nand_do_read_ops()'. In such cases, we use the page cache (chip->buffers->databuf) as an intermediate buffer before dumping to the client buffer. However, there are also cases where this buffer is not cleanly reusable. In those cases, we need to make sure that we explicitly invalidate the cache.
This patch prevents accidental reusage of the page cache, and for me, this solves some problems I come across when reading a corrupted BBT from flash (NAND_BBT_USE_FLASH and NAND_BBT_NO_OOB).
Note: the rare "unaligned" case is a result of the extra BBT pattern + version located in the data area instead of OOB.
Also, this patch disables caching on raw reads, since we are reading without error correction. This is, obviously, prone to errors and should not be cached.
--- drivers/mtd/nand/nand_base.c | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-)
drivers/mtd/nand/nand_base.c +10 -2
@@ -1479,14 +1479,22 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,else ret = chip->ecc.read_page (mtd, chip, bufpoi, page); -if (ret <0 ) +if (ret <0 ) { +if (!aligned) +/* Invalidate page cache */ + chip->pagebuf =-1 ;break ; + }/* Transfer not aligned data */ if (!aligned) {if (!NAND_SUBPAGE_READ (chip) && !oob && - !(mtd->ecc_stats.failed - stats.failed)) + !(mtd->ecc_stats.failed - stats.failed) && + (ops->mode !=MTD_OPS_RAW )) chip->pagebuf = realpage; +else +/* Invalidate page cache */ + chip->pagebuf =-1 ;memcpy (buf, chip->buffers->databuf + col, bytes); }
Signature · 1 line
1.7.5.4
PATCH 14/14 mtd: nand: switch `check_pattern()' to standard `memcmp()'
In reply to Brian NorrisA portion of the check_pattern()' function is basically a memcmp()'. Since it's possible for `memcmp()' to be optimized for a particular architecture, we should use it instead.
--- drivers/mtd/nand/nand_bbt.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-)
drivers/mtd/nand/nand_bbt.c +2 -4
@@ -107,10 +107,8 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc p += end;/* Compare the pattern */ -for (i =0 ; i < td->len; i++) { -if (p[i] != td->pattern[i]) -return -1 ; - } +if (memcmp (p, td->pattern, td->len)) +return -1 ;if (td->options &NAND_BBT_SCANEMPTY ) { p += td->len;
Signature · 1 line
1.7.5.4