Commit 7e7e4730 authored by Baruch Siach's avatar Baruch Siach Committed by Brian Norris

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: default avatarSascha Hauer <s.hauer@pengutronix.de>
Acked-by: default avatarUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: default avatarBaruch Siach <baruch@tkos.co.il>
Signed-off-by: default avatarBrian Norris <computersforpeace@gmail.com>
parent 35d5d20e
...@@ -189,6 +189,7 @@ struct mxc_nand_host { ...@@ -189,6 +189,7 @@ struct mxc_nand_host {
int clk_act; int clk_act;
int irq; int irq;
int eccsize; int eccsize;
int used_oobsize;
int active_cs; int active_cs;
struct completion op_completion; struct completion op_completion;
...@@ -827,7 +828,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom) ...@@ -827,7 +828,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
u16 sparebuf_size = host->devtype_data->spare_len; u16 sparebuf_size = host->devtype_data->spare_len;
/* size of oob chunk for all but possibly the last one */ /* 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) { if (bfrom) {
for (i = 0; i < num_chunks - 1; i++) for (i = 0; i < num_chunks - 1; i++)
...@@ -838,7 +839,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom) ...@@ -838,7 +839,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
/* the last chunk */ /* the last chunk */
memcpy32_fromio(d + i * oob_chunk_size, memcpy32_fromio(d + i * oob_chunk_size,
s + i * sparebuf_size, s + i * sparebuf_size,
mtd->oobsize - i * oob_chunk_size); host->used_oobsize - i * oob_chunk_size);
} else { } else {
for (i = 0; i < num_chunks - 1; i++) for (i = 0; i < num_chunks - 1; i++)
memcpy32_toio(&s[i * sparebuf_size], memcpy32_toio(&s[i * sparebuf_size],
...@@ -848,7 +849,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom) ...@@ -848,7 +849,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
/* the last chunk */ /* the last chunk */
memcpy32_toio(&s[oob_chunk_size * sparebuf_size], memcpy32_toio(&s[oob_chunk_size * sparebuf_size],
&d[i * oob_chunk_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) ...@@ -1606,6 +1607,15 @@ static int mxcnd_probe(struct platform_device *pdev)
else if (mtd->writesize == 4096) else if (mtd->writesize == 4096)
this->ecc.layout = host->devtype_data->ecclayout_4k; 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 (this->ecc.mode == NAND_ECC_HW) {
if (is_imx21_nfc(host) || is_imx27_nfc(host)) if (is_imx21_nfc(host) || is_imx27_nfc(host))
this->ecc.strength = 1; this->ecc.strength = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment