aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorKamal Dasu <kdasu.kdev@gmail.com>2016-06-09 17:17:54 -0400
committerBoris Brezillon <boris.brezillon@free-electrons.com>2016-06-13 11:03:23 -0400
commit02b88eea9f9cab82f5f4be234c64466503021f82 (patch)
treeb1e1f53c7a6d1605c19cd713079fb898e513a200 /drivers/mtd
parent1c7fe6b438433e16d5b1211380c305351ac38299 (diff)
mtd: brcmnand: Add check for erased page bitflips
Check for erased page bitflips in a page. And if well within threshold return data as all 0xff. Apply sw check for controller version < 7.2. Controller vesion >= 7.2 has hw support. Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/brcmnand/brcmnand.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index 0a54a0f5a4b1..f0b067229f7f 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -1602,6 +1602,56 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
1602 return ret; 1602 return ret;
1603} 1603}
1604 1604
1605/*
1606 * Check a page to see if it is erased (w/ bitflips) after an uncorrectable ECC
1607 * error
1608 *
1609 * Because the HW ECC signals an ECC error if an erase paged has even a single
1610 * bitflip, we must check each ECC error to see if it is actually an erased
1611 * page with bitflips, not a truly corrupted page.
1612 *
1613 * On a real error, return a negative error code (-EBADMSG for ECC error), and
1614 * buf will contain raw data.
1615 * Otherwise, buf gets filled with 0xffs and return the maximum number of
1616 * bitflips-per-ECC-sector to the caller.
1617 *
1618 */
1619static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd,
1620 struct nand_chip *chip, void *buf, u64 addr)
1621{
1622 int i, sas;
1623 void *oob = chip->oob_poi;
1624 int bitflips = 0;
1625 int page = addr >> chip->page_shift;
1626 int ret;
1627
1628 if (!buf) {
1629 buf = chip->buffers->databuf;
1630 /* Invalidate page cache */
1631 chip->pagebuf = -1;
1632 }
1633
1634 sas = mtd->oobsize / chip->ecc.steps;
1635
1636 /* read without ecc for verification */
1637 chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
1638 ret = chip->ecc.read_page_raw(mtd, chip, buf, true, page);
1639 if (ret)
1640 return ret;
1641
1642 for (i = 0; i < chip->ecc.steps; i++, oob += sas) {
1643 ret = nand_check_erased_ecc_chunk(buf, chip->ecc.size,
1644 oob, sas, NULL, 0,
1645 chip->ecc.strength);
1646 if (ret < 0)
1647 return ret;
1648
1649 bitflips = max(bitflips, ret);
1650 }
1651
1652 return bitflips;
1653}
1654
1605static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, 1655static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip,
1606 u64 addr, unsigned int trans, u32 *buf, u8 *oob) 1656 u64 addr, unsigned int trans, u32 *buf, u8 *oob)
1607{ 1657{
@@ -1632,6 +1682,18 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip,
1632 } 1682 }
1633 1683
1634 if (mtd_is_eccerr(err)) { 1684 if (mtd_is_eccerr(err)) {
1685 /*
1686 * Controller version 7.2 has hw encoder to detect erased page
1687 * bitflips, apply sw verification for older controllers only
1688 */
1689 if (ctrl->nand_version < 0x0702) {
1690 err = brcmstb_nand_verify_erased_page(mtd, chip, buf,
1691 addr);
1692 /* erased page bitflips corrected */
1693 if (err > 0)
1694 return err;
1695 }
1696
1635 dev_dbg(ctrl->dev, "uncorrectable error at 0x%llx\n", 1697 dev_dbg(ctrl->dev, "uncorrectable error at 0x%llx\n",
1636 (unsigned long long)err_addr); 1698 (unsigned long long)err_addr);
1637 mtd->ecc_stats.failed++; 1699 mtd->ecc_stats.failed++;