mtd: nand: localize ECC failures per page
authorBrian Norris <computersforpeace@gmail.com>
Tue, 3 Dec 2013 19:04:14 +0000 (11:04 -0800)
committerBrian Norris <computersforpeace@gmail.com>
Tue, 14 Jan 2014 07:12:38 +0000 (23:12 -0800)
ECC failures can be tracked at the page level, not the do_read_ops level
(i.e., a potentially multi-page transaction).

This helps prepare for READ RETRY support.

Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Acked-by: Huang Shijie <b32955@freescale.com>
drivers/mtd/nand/nand_base.c

index 404e83d7e3dad766c1d67c13dc19c398460af619..b5c3768b32aef6d62fbe9f0555ca2b1f3327cc55 100644 (file)
@@ -1422,7 +1422,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 {
        int chipnr, page, realpage, col, bytes, aligned, oob_required;
        struct nand_chip *chip = mtd->priv;
-       struct mtd_ecc_stats stats;
        int ret = 0;
        uint32_t readlen = ops->len;
        uint32_t oobreadlen = ops->ooblen;
@@ -1431,8 +1430,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 
        uint8_t *bufpoi, *oob, *buf;
        unsigned int max_bitflips = 0;
-
-       stats = mtd->ecc_stats;
+       bool ecc_fail = false;
 
        chipnr = (int)(from >> chip->chip_shift);
        chip->select_chip(mtd, chipnr);
@@ -1447,6 +1445,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
        oob_required = oob ? 1 : 0;
 
        while (1) {
+               unsigned int ecc_failures = mtd->ecc_stats.failed;
+
                bytes = min(mtd->writesize - col, readlen);
                aligned = (bytes == mtd->writesize);
 
@@ -1483,7 +1483,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                        /* Transfer not aligned data */
                        if (!aligned) {
                                if (!NAND_HAS_SUBPAGE_READ(chip) && !oob &&
-                                   !(mtd->ecc_stats.failed - stats.failed) &&
+                                   !(mtd->ecc_stats.failed - ecc_failures) &&
                                    (ops->mode != MTD_OPS_RAW)) {
                                        chip->pagebuf = realpage;
                                        chip->pagebuf_bitflips = ret;
@@ -1513,6 +1513,9 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                                else
                                        nand_wait_ready(mtd);
                        }
+
+                       if (mtd->ecc_stats.failed - ecc_failures)
+                               ecc_fail = true;
                } else {
                        memcpy(buf, chip->buffers->databuf + col, bytes);
                        buf += bytes;
@@ -1547,7 +1550,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
        if (ret < 0)
                return ret;
 
-       if (mtd->ecc_stats.failed - stats.failed)
+       if (ecc_fail)
                return -EBADMSG;
 
        return max_bitflips;