mtd: mxc_nand: limit the size of used oob

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Tue Jun 23 10:59:05 PDT 2015


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=7e7e4730c178f32a14b781f7c55564d99c4dda3f
Commit:     7e7e4730c178f32a14b781f7c55564d99c4dda3f
Parent:     35d5d20efad8a04c8c002c7f31241dff973977a6
Author:     Baruch Siach <baruch at tkos.co.il>
AuthorDate: Wed May 13 11:17:37 2015 +0300
Committer:  Brian Norris <computersforpeace at gmail.com>
CommitDate: Wed May 20 15:29:53 2015 -0700

    mtd: mxc_nand: limit the size of used oob
    
    For 4k pages the i.MX NFC hardware uses no more than 218 bytes for 8bit ECC
    data. Larger oobsize confuses the logic of copy_spare(). Limit the size of used
    oob size to avoid that.
    
    Reviewed-by: Sascha Hauer <s.hauer at pengutronix.de>
    Acked-by: Uwe Kleine-König <u.kleine-koenig at pengutronix.de>
    Signed-off-by: Baruch Siach <baruch at tkos.co.il>
    Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/mxc_nand.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 5bbc1c5..ceeb61c 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -189,6 +189,7 @@ struct mxc_nand_host {
 	int			clk_act;
 	int			irq;
 	int			eccsize;
+	int			used_oobsize;
 	int			active_cs;
 
 	struct completion	op_completion;
@@ -827,7 +828,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
 	u16 sparebuf_size = host->devtype_data->spare_len;
 
 	/* size of oob chunk for all but possibly the last one */
-	oob_chunk_size = (mtd->oobsize / num_chunks) & ~1;
+	oob_chunk_size = (host->used_oobsize / num_chunks) & ~1;
 
 	if (bfrom) {
 		for (i = 0; i < num_chunks - 1; i++)
@@ -838,7 +839,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
 		/* the last chunk */
 		memcpy32_fromio(d + i * oob_chunk_size,
 				s + i * sparebuf_size,
-				mtd->oobsize - i * oob_chunk_size);
+				host->used_oobsize - i * oob_chunk_size);
 	} else {
 		for (i = 0; i < num_chunks - 1; i++)
 			memcpy32_toio(&s[i * sparebuf_size],
@@ -848,7 +849,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
 		/* the last chunk */
 		memcpy32_toio(&s[oob_chunk_size * sparebuf_size],
 			      &d[i * oob_chunk_size],
-			      mtd->oobsize - i * oob_chunk_size);
+			      host->used_oobsize - i * oob_chunk_size);
 	}
 }
 
@@ -1606,6 +1607,15 @@ static int mxcnd_probe(struct platform_device *pdev)
 	else if (mtd->writesize == 4096)
 		this->ecc.layout = host->devtype_data->ecclayout_4k;
 
+	/*
+	 * Experimentation shows that i.MX NFC can only handle up to 218 oob
+	 * bytes. Limit used_oobsize to 218 so as to not confuse copy_spare()
+	 * into copying invalid data to/from the spare IO buffer, as this
+	 * might cause ECC data corruption when doing sub-page write to a
+	 * partially written page.
+	 */
+	host->used_oobsize = min(mtd->oobsize, 218U);
+
 	if (this->ecc.mode == NAND_ECC_HW) {
 		if (is_imx21_nfc(host) || is_imx27_nfc(host))
 			this->ecc.strength = 1;



More information about the linux-mtd-cvs mailing list