From 67a9ad9b8a6f6ea76ef8fc484ae49970d72d5534 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 14 May 2014 14:58:06 -0300 Subject: mtd: nand: Warn the user if the selected ECC strength is too weak This commit makes use of the chip->ecc_strength_ds and chip->ecc_step_ds which contain the datasheet minimum requested ECC strength to produce a noisy warning if the configured ECC strength is weaker. Signed-off-by: Ezequiel Garcia Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 0c1593be69e3..41167e9e991e 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3794,6 +3794,39 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, } EXPORT_SYMBOL(nand_scan_ident); +/* + * Check if the chip configuration meet the datasheet requirements. + + * If our configuration corrects A bits per B bytes and the minimum + * required correction level is X bits per Y bytes, then we must ensure + * both of the following are true: + * + * (1) A / B >= X / Y + * (2) A >= X + * + * Requirement (1) ensures we can correct for the required bitflip density. + * Requirement (2) ensures we can correct even when all bitflips are clumped + * in the same sector. + */ +static bool nand_ecc_strength_good(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd->priv; + struct nand_ecc_ctrl *ecc = &chip->ecc; + int corr, ds_corr; + + if (ecc->size == 0 || chip->ecc_step_ds == 0) + /* Not enough information */ + return true; + + /* + * We get the number of corrected bits per page to compare + * the correction density. + */ + corr = (mtd->writesize * ecc->strength) / ecc->size; + ds_corr = (mtd->writesize * chip->ecc_strength_ds) / chip->ecc_step_ds; + + return corr >= ds_corr && ecc->strength >= chip->ecc_strength_ds; +} /** * nand_scan_tail - [NAND Interface] Scan for the NAND device @@ -4014,6 +4047,9 @@ int nand_scan_tail(struct mtd_info *mtd) ecc->layout->oobavail += ecc->layout->oobfree[i].length; mtd->oobavail = ecc->layout->oobavail; + /* ECC sanity check: warn noisily if it's too weak */ + WARN_ON(!nand_ecc_strength_good(mtd)); + /* * Set the number of read / write steps for one page depending on ECC * mode. -- cgit v1.2.3