diff mbox

[U-Boot,1/2] mtd: nand: omap: fix sw->hw->sw ecc switch

Message ID 1387214342-7411-2-git-send-email-nikita@compulab.co.il
State Accepted
Delegated to: Scott Wood
Headers show

Commit Message

Nikita Kiryanov Dec. 16, 2013, 5:19 p.m. UTC
When switching ecc mode, omap_select_ecc_scheme() assigns the appropriate values
into the current nand chip's ecc.layout struct. This is done under the
assumption that the struct exists only to store values, so it is OK to overwrite
it, but there is at least one situation where this assumption is incorrect:

When switching to 1 bit hamming code sw ecc, the job of assigning layout data
is outsourced to nand_scan_tail(), which simply assigns into ecc.layout a
pointer to an existing struct prefilled with the appropriate values. This struct
doubles as both data and layout definition, and therefore shouldn't be
overwritten, but on the next switch to hardware ecc, this is exactly what's
going to happen. The next time the user switches to software ecc, they're
going to get a messed up ecc layout.

Prevent this and possible similar bugs by explicitly using the
private-to-omap_gpmc.c omap_ecclayout struct when switching ecc mode.

Cc: Scott Wood <scottwood@freescale.com>
Cc: Pekon Gupta <pekon@ti.com>
Signed-off-by: Nikita Kiryanov <nikita@compulab.co.il>
---
 drivers/mtd/nand/omap_gpmc.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

Comments

Scott Wood Dec. 17, 2013, 11:47 p.m. UTC | #1
On Mon, Dec 16, 2013 at 07:19:01PM +0200, Nikita Kiryanov wrote:
> When switching ecc mode, omap_select_ecc_scheme() assigns the appropriate values
> into the current nand chip's ecc.layout struct. This is done under the
> assumption that the struct exists only to store values, so it is OK to overwrite
> it, but there is at least one situation where this assumption is incorrect:
> 
> When switching to 1 bit hamming code sw ecc, the job of assigning layout data
> is outsourced to nand_scan_tail(), which simply assigns into ecc.layout a
> pointer to an existing struct prefilled with the appropriate values. This struct
> doubles as both data and layout definition, and therefore shouldn't be
> overwritten, but on the next switch to hardware ecc, this is exactly what's
> going to happen. The next time the user switches to software ecc, they're
> going to get a messed up ecc layout.
> 
> Prevent this and possible similar bugs by explicitly using the
> private-to-omap_gpmc.c omap_ecclayout struct when switching ecc mode.
> 
> Cc: Scott Wood <scottwood@freescale.com>
> Cc: Pekon Gupta <pekon@ti.com>
> Signed-off-by: Nikita Kiryanov <nikita@compulab.co.il>
> 
> ---
> drivers/mtd/nand/omap_gpmc.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)

Applied to u-boot-nand-flash.git

-Scott
diff mbox

Patch

diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index e61788f..fda1df2 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -761,7 +761,7 @@  static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
 static int omap_select_ecc_scheme(struct nand_chip *nand,
 	enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
 	struct nand_bch_priv	*bch		= nand->priv;
-	struct nand_ecclayout	*ecclayout	= nand->ecc.layout;
+	struct nand_ecclayout	*ecclayout	= &omap_ecclayout;
 	int eccsteps = pagesize / SECTOR_BYTES;
 	int i;
 
@@ -895,6 +895,11 @@  static int omap_select_ecc_scheme(struct nand_chip *nand,
 		debug("nand: error: ecc scheme not enabled or supported\n");
 		return -EINVAL;
 	}
+
+	/* nand_scan_tail() sets ham1 sw ecc; hw ecc layout is set by driver */
+	if (ecc_scheme != OMAP_ECC_HAM1_CODE_SW)
+		nand->ecc.layout = ecclayout;
+
 	return 0;
 }