diff options
author | Pekon Gupta <pekon@ti.com> | 2014-03-18 18:56:46 +0530 |
---|---|---|
committer | Brian Norris <computersforpeace@gmail.com> | 2014-03-20 01:47:59 -0700 |
commit | 13fbe0641ef4132cac936ac352194d2fe9ddf824 (patch) | |
tree | a2fe1d0f604d953f291ed29dd068bb7101dde256 | |
parent | b08e1f632c79e9e75bf2ae58107df27d0e35b459 (diff) |
mtd: nand: omap: ecc.correct: omap_elm_correct_data: fix programmed-page bit-flip correction logic
This patch updates following checks when bit-flips are detected by ELM:
- Do not evaluate bit-flips when un-correctable bit-flips is reported by ELM,
because as per [1] when ELM reports an un-correctable bit-flips,
'number of error' field in its ELM_LOCATION_STATUS register is also invalid.
- Return with error-code '-EBADMSG' on detection of un-correctable bit-flip.
- Return with error-code '-EBADMSG' when bit-flips position is outside current
Sector and OOB area.
[1] ELM IP spec Table-25 ELM_LOCATION_STATUS Register.
ELM_LOCATION_STATUS[8] = ECC_CORRECTABLE: Error location process exit status
0x0: ECC error location process failed.
Number of errors and error locations are invalid.
0x1: all errors were successfully located.
Number of errors and error locations are valid.
Tested-by: Stefan Roese <sr@denx.de>
Signed-off-by: Pekon Gupta <pekon@ti.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
-rw-r--r-- | drivers/mtd/nand/omap2.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 39e3f50023d5..4f067f0f4e52 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1353,6 +1353,7 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, int bitflip_count; bool is_error_reported = false; u32 bit_pos, byte_pos, error_max, pos; + int err; switch (info->ecc_opt) { case OMAP_ECC_BCH4_CODE_HW: @@ -1434,8 +1435,12 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, /* Decode BCH error using ELM module */ elm_decode_bch_error_page(info->elm_dev, ecc_vec, err_vec); + err = 0; for (i = 0; i < eccsteps; i++) { - if (err_vec[i].error_reported) { + if (err_vec[i].error_uncorrectable) { + pr_err("nand: uncorrectable bit-flips found\n"); + err = -EBADMSG; + } else if (err_vec[i].error_reported) { for (j = 0; j < err_vec[i].error_count; j++) { switch (info->ecc_opt) { case OMAP_ECC_BCH4_CODE_HW: @@ -1457,13 +1462,22 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, byte_pos = (error_max - pos - 1) / 8; if (pos < error_max) { - if (byte_pos < 512) + if (byte_pos < 512) { + pr_debug("bitflip@dat[%d]=%x\n", + byte_pos, data[byte_pos]); data[byte_pos] ^= 1 << bit_pos; - else + } else { + pr_debug("bitflip@oob[%d]=%x\n", + (byte_pos - 512), + spare_ecc[byte_pos - 512]); spare_ecc[byte_pos - 512] ^= 1 << bit_pos; + } + } else { + pr_err("invalid bit-flip @ %d:%d\n", + byte_pos, bit_pos); + err = -EBADMSG; } - /* else, not interested to correct ecc */ } } @@ -1475,12 +1489,7 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, spare_ecc += ecc->bytes; } - for (i = 0; i < eccsteps; i++) - /* Return error if uncorrectable error present */ - if (err_vec[i].error_uncorrectable) - return -EINVAL; - - return stat; + return (err) ? err : stat; } /** |