Commit bc468fa6a8dcfbe809eef7efe90150afbeca2fac

Authored by Peng Fan
Committed by Ye Li
1 parent b4a15f89ed

MLK-12693-1 nand: mxs: fix the bitflips for erased page when uncorrectable error

This patch is porting from linux:
http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/commit/?h=imx_4.1.15_1.0.0_ga&id=3d42fcece496224fde59f9343763fb2dfc5b0768

"
We may meet the bitflips in reading an erased page(contains all 0xFF),
this may causes the UBIFS corrupt, please see the log from Elie:

-----------------------------------------------------------------
[    3.831323] UBI warning: ubi_io_read: error -74 (ECC error) while reading 16384 bytes from PEB 443:245760, read only 16384 bytes, retry
[    3.845026] UBI warning: ubi_io_read: error -74 (ECC error) while reading 16384 bytes from PEB 443:245760, read only 16384 bytes, retry
[    3.858710] UBI warning: ubi_io_read: error -74 (ECC error) while reading 16384 bytes from PEB 443:245760, read only 16384 bytes, retry
[    3.872408] UBI error: ubi_io_read: error -74 (ECC error) while reading 16384 bytes from PEB 443:245760, read 16384 bytes
...
[    4.011529] UBIFS error (pid 36): ubifs_recover_leb: corrupt empty space LEB 27:237568, corruption starts at 9815
[    4.021897] UBIFS error (pid 36): ubifs_scanned_corruption: corruption at LEB 27:247383
[    4.030000] UBIFS error (pid 36): ubifs_scanned_corruption: first 6569 bytes from LEB 27:247383
-----------------------------------------------------------------

This patch does a check for the uncorrectable failure in the following steps:

   [0] set the threshold.
       The threshold is set based on the truth:
       "A single 0 bit will lead to gf_len(13 or 14) bits 0 after the BCH
        do the ECC."

        For the sake of safe, we will set the threshold with half the gf_len, and
        do not make it bigger the ECC strength.

   [1] count the bitflips of the current ECC chunk, assume it is N.

   [2] if the (N <= threshold) is true, we continue to read out the page with
       ECC disabled. and we count the bitflips again, assume it is N2.
       (We read out the whole page, not just a chunk, this makes the check
        more strictly, and make the code more simple.)

   [3] if the (N2 <= threshold) is true again, we can regard this is a erased
       page. This is because a real erased page is full of 0xFF(maybe also has
       several bitflips), while a page contains the 0xFF data will definitely
       has many bitflips in the ECC parity areas.

   [4] if the [3] fails, we can regard this is a page filled with the '0xFF'
       data.
"

Signed-off-by: Peng Fan <peng.fan@nxp.com>
(cherry picked from commit ceb324a2914487aa517a6c70a06a20b5e3438fda)
(cherry picked from commit 026751697e41c7376414a8716cf0ea4bf998b85f)
(cherry picked from commit 93b481f07b8cb59c733f420bebea77ac484f9036)
(cherry picked from commit eefb30b8e68d522bd315ed884c36cb9b7e917f71)

Showing 1 changed file with 44 additions and 0 deletions Side-by-side Diff

drivers/mtd/nand/raw/mxs_nand.c
... ... @@ -612,6 +612,45 @@
612 612 return buf;
613 613 }
614 614  
  615 +static bool mxs_nand_erased_page(struct mtd_info *mtd, struct nand_chip *nand,
  616 + uint8_t *buf, int chunk, int page)
  617 +{
  618 + struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
  619 + struct bch_geometry *geo = &nand_info->bch_geometry;
  620 + unsigned int flip_bits = 0, flip_bits_noecc = 0;
  621 + unsigned int threshold;
  622 + unsigned int base = geo->ecc_chunkn_size * chunk;
  623 + uint32_t *dma_buf = (uint32_t *)buf;
  624 + int i;
  625 +
  626 + threshold = geo->gf_len / 2;
  627 + if (threshold > geo->ecc_strength)
  628 + threshold = geo->ecc_strength;
  629 +
  630 + for (i = 0; i < geo->ecc_chunkn_size; i++) {
  631 + flip_bits += hweight8(~buf[base + i]);
  632 + if (flip_bits > threshold)
  633 + return false;
  634 + }
  635 +
  636 + nand->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
  637 + nand->read_buf(mtd, buf, mtd->writesize);
  638 +
  639 + for (i = 0; i < mtd->writesize / 4; i++) {
  640 + flip_bits_noecc += hweight32(~dma_buf[i]);
  641 + if (flip_bits_noecc > threshold)
  642 + return false;
  643 + }
  644 +
  645 + mtd->ecc_stats.corrected += flip_bits;
  646 +
  647 + memset(buf, 0xff, mtd->writesize);
  648 +
  649 + printf("The page(%d) is an erased page(%d,%d,%d,%d).\n", page, chunk, threshold, flip_bits, flip_bits_noecc);
  650 +
  651 + return true;
  652 +}
  653 +
615 654 /*
616 655 * Read a page from NAND.
617 656 */
... ... @@ -715,6 +754,8 @@
715 754 goto rtn;
716 755 }
717 756  
  757 + mxs_nand_return_dma_descs(nand_info);
  758 +
718 759 /* Invalidate caches */
719 760 mxs_nand_inval_data_buf(nand_info);
720 761  
... ... @@ -731,6 +772,9 @@
731 772 continue;
732 773  
733 774 if (status[i] == 0xfe) {
  775 + if (mxs_nand_erased_page(mtd, nand,
  776 + nand_info->data_buf, i, page))
  777 + break;
734 778 failed++;
735 779 continue;
736 780 }