OSDN Git Service

mtd: nand: atmel: correct bitflips in erased pages for pre-sama5d4 SoCs
authorBoris Brezillon <boris.brezillon@free-electrons.com>
Tue, 1 Mar 2016 13:11:52 +0000 (14:11 +0100)
committerBoris Brezillon <boris.brezillon@free-electrons.com>
Tue, 19 Apr 2016 20:04:50 +0000 (22:04 +0200)
New atmel SoCs are able to fix bitflips in erased pages, but old ones
are still impacted by this problem. Use nand_check_erased_ecc_chunk() to
handle this case.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Reported-by: Herve Codina <herve.CODINA@celad.com>
Reviewed-by: Herve Codina <herve.CODINA@celad.com>
Tested-by: Herve Codina <herve.CODINA@celad.com>
drivers/mtd/nand/atmel_nand.c

index 20cbaab..0b5da72 100644 (file)
@@ -863,17 +863,6 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf,
        uint8_t *buf_pos;
        int max_bitflips = 0;
 
-       /* If can correct bitfilps from erased page, do the normal check */
-       if (host->caps->pmecc_correct_erase_page)
-               goto normal_check;
-
-       for (i = 0; i < nand_chip->ecc.total; i++)
-               if (ecc[i] != 0xff)
-                       goto normal_check;
-       /* Erased page, return OK */
-       return 0;
-
-normal_check:
        for (i = 0; i < nand_chip->ecc.steps; i++) {
                err_nbr = 0;
                if (pmecc_stat & 0x1) {
@@ -884,16 +873,30 @@ normal_check:
                        pmecc_get_sigma(mtd);
 
                        err_nbr = pmecc_err_location(mtd);
-                       if (err_nbr == -1) {
+                       if (err_nbr >= 0) {
+                               pmecc_correct_data(mtd, buf_pos, ecc, i,
+                                                  nand_chip->ecc.bytes,
+                                                  err_nbr);
+                       } else if (!host->caps->pmecc_correct_erase_page) {
+                               u8 *ecc_pos = ecc + (i * nand_chip->ecc.bytes);
+
+                               /* Try to detect erased pages */
+                               err_nbr = nand_check_erased_ecc_chunk(buf_pos,
+                                                       host->pmecc_sector_size,
+                                                       ecc_pos,
+                                                       nand_chip->ecc.bytes,
+                                                       NULL, 0,
+                                                       nand_chip->ecc.strength);
+                       }
+
+                       if (err_nbr < 0) {
                                dev_err(host->dev, "PMECC: Too many errors\n");
                                mtd->ecc_stats.failed++;
                                return -EIO;
-                       } else {
-                               pmecc_correct_data(mtd, buf_pos, ecc, i,
-                                       nand_chip->ecc.bytes, err_nbr);
-                               mtd->ecc_stats.corrected += err_nbr;
-                               max_bitflips = max_t(int, max_bitflips, err_nbr);
                        }
+
+                       mtd->ecc_stats.corrected += err_nbr;
+                       max_bitflips = max_t(int, max_bitflips, err_nbr);
                }
                pmecc_stat >>= 1;
        }