mtd: nand: pxa3xx: re-read a page in raw mode on uncorrectable error
authorMiquel Raynal <miquel.raynal@bootlin.com>
Thu, 11 Oct 2018 15:45:43 +0000 (17:45 +0200)
committerJagan Teki <jagan@amarulasolutions.com>
Thu, 22 Nov 2018 06:08:05 +0000 (11:38 +0530)
This only applies on BCH path.

When an empty page is read, it triggers an uncorrectable error. While
this is expected, the ECC engine might produce itself bitflips in the
read data under certain layouts. To overcome this situation, always
re-read the entire page in raw mode and check for the whole page to be
empty.

Also report the right number of bitflips if there are any.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Acked-by: Jagan Teki <jagan@openedev.com>
drivers/mtd/nand/raw/pxa3xx_nand.c

index 4545973..492485b 100644 (file)
@@ -1237,6 +1237,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 {
        struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
        struct pxa3xx_nand_info *info = host->info_data;
+       int bf;
 
        chip->read_buf(mtd, buf, mtd->writesize);
        chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -1244,12 +1245,30 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
        if (info->retcode == ERR_CORERR && info->use_ecc) {
                mtd->ecc_stats.corrected += info->ecc_err_cnt;
 
-       } else if (info->retcode == ERR_UNCORERR) {
+       } else if (info->retcode == ERR_UNCORERR && info->ecc_bch) {
                /*
-                * for blank page (all 0xff), HW will calculate its ECC as
-                * 0, which is different from the ECC information within
-                * OOB, ignore such uncorrectable errors
+                * Empty pages will trigger uncorrectable errors. Re-read the
+                * entire page in raw mode and check for bits not being "1".
+                * If there are more than the supported strength, then it means
+                * this is an actual uncorrectable error.
                 */
+               chip->ecc.read_page_raw(mtd, chip, buf, oob_required, page);
+               bf = nand_check_erased_ecc_chunk(buf, mtd->writesize,
+                                                chip->oob_poi, mtd->oobsize,
+                                                NULL, 0, chip->ecc.strength);
+               if (bf < 0) {
+                       mtd->ecc_stats.failed++;
+               } else if (bf) {
+                       mtd->ecc_stats.corrected += bf;
+                       info->max_bitflips = max_t(unsigned int,
+                                                  info->max_bitflips, bf);
+                       info->retcode = ERR_CORERR;
+               } else {
+                       info->retcode = ERR_NONE;
+               }
+
+       } else if (info->retcode == ERR_UNCORERR && !info->ecc_bch) {
+               /* Raw read is not supported with Hamming ECC engine */
                if (is_buf_blank(buf, mtd->writesize))
                        info->retcode = ERR_NONE;
                else