mtd: nand: omap: ecc.correct: omap_elm_correct_data: fix programmed-page bit-flip correction logic

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Sat Apr 5 02:59:04 EDT 2014


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=13fbe0641ef4132cac936ac352194d2fe9ddf824
Commit:     13fbe0641ef4132cac936ac352194d2fe9ddf824
Parent:     b08e1f632c79e9e75bf2ae58107df27d0e35b459
Author:     Pekon Gupta <pekon at ti.com>
AuthorDate: Tue Mar 18 18:56:46 2014 +0530
Committer:  Brian Norris <computersforpeace at gmail.com>
CommitDate: Thu Mar 20 01:47:59 2014 -0700

    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 at denx.de>
    Signed-off-by: Pekon Gupta <pekon at ti.com>
    Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/omap2.c | 29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 39e3f50..4f067f0 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 at dat[%d]=%x\n",
+						     byte_pos, data[byte_pos]);
 						data[byte_pos] ^= 1 << bit_pos;
-					else
+					} else {
+						pr_debug("bitflip at 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;
 }
 
 /**



More information about the linux-mtd-cvs mailing list