mtd: nand: pxa3xx: re-read a page in raw mode on uncorrectable error

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>
This commit is contained in:
Miquel Raynal 2018-10-11 17:45:43 +02:00 committed by Jagan Teki
parent 6293b0361d
commit af61ea27f5

View 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