mtd: rawnand: Ensure the number of bitflips is consistent
authorMiquel Raynal <miquel.raynal@bootlin.com>
Tue, 19 May 2020 07:45:44 +0000 (09:45 +0200)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Sun, 24 May 2020 18:48:11 +0000 (20:48 +0200)
The main NAND read page function can loop over "page reads" many times
in if the reading reports uncorrectable error(s) and if the chip
supports the read_retry feature.

In this case, the number of bitflips is summarized between
attempts. Fix this by re-initializing the entire mtd_ecc_stats object
each time we retry.

Suggested-by: Boris Brezillon <boris.brezillon@collabora.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Link: https://lore.kernel.org/linux-mtd/20200519074549.23673-4-miquel.raynal@bootlin.com
drivers/mtd/nand/raw/nand_base.c

index 79e8052..475647e 100644 (file)
@@ -3295,7 +3295,7 @@ static int nand_do_read_ops(struct nand_chip *chip, loff_t from,
        oob_required = oob ? 1 : 0;
 
        while (1) {
-               unsigned int ecc_failures = mtd->ecc_stats.failed;
+               struct mtd_ecc_stats ecc_stats = mtd->ecc_stats;
 
                bytes = min(mtd->writesize - col, readlen);
                aligned = (bytes == mtd->writesize);
@@ -3346,7 +3346,7 @@ read_retry:
                         */
                        if (use_bounce_buf) {
                                if (!NAND_HAS_SUBPAGE_READ(chip) && !oob &&
-                                   !(mtd->ecc_stats.failed - ecc_failures) &&
+                                   !(mtd->ecc_stats.failed - ecc_stats.failed) &&
                                    (ops->mode != MTD_OPS_RAW)) {
                                        chip->pagecache.page = realpage;
                                        chip->pagecache.bitflips = ret;
@@ -3369,7 +3369,7 @@ read_retry:
 
                        nand_wait_readrdy(chip);
 
-                       if (mtd->ecc_stats.failed - ecc_failures) {
+                       if (mtd->ecc_stats.failed - ecc_stats.failed) {
                                if (retry_mode + 1 < chip->read_retries) {
                                        retry_mode++;
                                        ret = nand_setup_read_retry(chip,
@@ -3377,8 +3377,8 @@ read_retry:
                                        if (ret < 0)
                                                break;
 
-                                       /* Reset failures; retry */
-                                       mtd->ecc_stats.failed = ecc_failures;
+                                       /* Reset ecc_stats; retry */
+                                       mtd->ecc_stats = ecc_stats;
                                        goto read_retry;
                                } else {
                                        /* No more retry modes; real failure */