summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPekon Gupta <pekon@ti.com>2014-03-18 18:56:46 +0530
committerBrian Norris <computersforpeace@gmail.com>2014-03-20 01:47:59 -0700
commit13fbe0641ef4132cac936ac352194d2fe9ddf824 (patch)
treea2fe1d0f604d953f291ed29dd068bb7101dde256
parentb08e1f632c79e9e75bf2ae58107df27d0e35b459 (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.c29
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;
}
/**