From linux-mtd at lists.infradead.org  Fri Feb 14 15:59:01 2014
From: linux-mtd at lists.infradead.org (Linux-MTD Mailing List)
Date: Fri, 14 Feb 2014 20:59:01 +0000
Subject: mtd: nand: fix off-by-one read retry mode counting
Message-ID: <E1WEPqf-0003xC-BH@bombadil.infradead.org>

Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=28fa65e643ed7cf753e89db20745e264c41f3682
Commit:     28fa65e643ed7cf753e89db20745e264c41f3682
Parent:     b28a960c42fcd9cfc987441fa6d1c1a471f0f9ed
Author:     Brian Norris <computersforpeace at gmail.com>
AuthorDate: Wed Feb 12 16:08:28 2014 -0800
Committer:  Brian Norris <computersforpeace at gmail.com>
CommitDate: Fri Feb 14 12:08:20 2014 -0800

    mtd: nand: fix off-by-one read retry mode counting
    
    A flash may support N read retry voltage threshold modes, numbered 0
    through N-1 (where mode 0 represents the initial state). However,
    nand_do_read_ops() tries to use mode 0 through N.
    
    This off-by-one error shows up, for instance, when using nanddump, and
    we have cycled through available modes:
    
        nand: setting READ RETRY mode 0
        nand: setting READ RETRY mode 1
        nand: setting READ RETRY mode 2
        nand: setting READ RETRY mode 3
        nand: setting READ RETRY mode 4
        nand: setting READ RETRY mode 5
        nand: setting READ RETRY mode 6
        nand: setting READ RETRY mode 7
        nand: setting READ RETRY mode 8
        libmtd: error!: cannot read 8192 bytes from mtd0 (eraseblock 20, offset 0)
                error 22 (Invalid argument)
        nanddump: error!: mtd_read
    
    Tested on Micron MT29F64G08CBCBBH1, with 8 retry modes.
    
    Signed-off-by: Brian Norris <computersforpeace at gmail.com>
    Acked-by: Huang Shijie <b32955 at freescale.com>
---
 drivers/mtd/nand/nand_base.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 59eba5d..9715a7b 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1584,7 +1584,7 @@ read_retry:
 			}
 
 			if (mtd->ecc_stats.failed - ecc_failures) {
-				if (retry_mode + 1 <= chip->read_retries) {
+				if (retry_mode + 1 < chip->read_retries) {
 					retry_mode++;
 					ret = nand_setup_read_retry(mtd,
 							retry_mode);


From linux-mtd at lists.infradead.org  Sun Feb 23 17:59:01 2014
From: linux-mtd at lists.infradead.org (Linux-MTD Mailing List)
Date: Sun, 23 Feb 2014 22:59:01 +0000
Subject: mtd: nand: omap: fix ecclayout->oobfree->offset
Message-ID: <E1WHi0j-0004iO-Ce@bombadil.infradead.org>

Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=aa6092f9835893290e77c3e24649def49dac1583
Commit:     aa6092f9835893290e77c3e24649def49dac1583
Parent:     eae39cb4934d3daab3ec828c5201c955b2e56af9
Author:     Pekon Gupta <pekon at ti.com>
AuthorDate: Mon Feb 17 13:11:24 2014 +0530
Committer:  Brian Norris <computersforpeace at gmail.com>
CommitDate: Sun Feb 23 14:49:57 2014 -0800

    mtd: nand: omap: fix ecclayout->oobfree->offset
    
    1) In current implementation, ecclayout->oobfree->offset is calculated with
     respect to ecclayout->eccpos[0] which is incorrect because ECC bytes may not
     be stored contiguously in OOB.
     So, this patch calculates ecclayout->oobfree->offset with respect to last
     ECC byte-position 'eccpos[ecclayout->eccbytes-1]'.
    
    2) ECC layout of some ecc-schemes expects reserved-markers at specific eccpos[]
     which should not be over-written by any file-system metadata.
     So this patch aligns oobfree->offset taking into account of such markers.
    
    CC: <stable at vger.kernel.org> # 3.13.x+
    Tested-by: Enric Balletbo i Serra <eballetbo at gmail.com>
    Tested-by: Stefan Roese <sr at denx.de>
    Signed-off-by: Pekon Gupta <pekon at ti.com>
    Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/omap2.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 34ef941..58685ab 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1832,8 +1832,9 @@ static int omap_nand_probe(struct platform_device *pdev)
 			oob_index		= 1;
 		for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
 			ecclayout->eccpos[i]	= oob_index;
-		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
-							ecclayout->eccbytes;
+		/* no reserved-marker in ecclayout for this ecc-scheme */
+		ecclayout->oobfree->offset	=
+				ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
 		break;
 
 	case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
@@ -1856,8 +1857,9 @@ static int omap_nand_probe(struct platform_device *pdev)
 			if (((i + 1) % nand_chip->ecc.bytes) == 0)
 				oob_index++;
 		}
-		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
-							ecclayout->eccbytes;
+		/* include reserved-marker in ecclayout->oobfree calculation */
+		ecclayout->oobfree->offset	= 1 +
+				ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
 		/* software bch library is used for locating errors */
 		nand_chip->ecc.priv		= nand_bch_init(mtd,
 							nand_chip->ecc.size,
@@ -1894,8 +1896,9 @@ static int omap_nand_probe(struct platform_device *pdev)
 		oob_index			= BADBLOCK_MARKER_LENGTH;
 		for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
 			ecclayout->eccpos[i]	= oob_index;
-		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
-							ecclayout->eccbytes;
+		/* reserved marker already included in ecclayout->eccbytes */
+		ecclayout->oobfree->offset	=
+				ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
 		/* This ECC scheme requires ELM H/W block */
 		if (is_elm_present(info, pdata->elm_of_node, BCH4_ECC) < 0) {
 			pr_err("nand: error: could not initialize ELM\n");
@@ -1929,8 +1932,9 @@ static int omap_nand_probe(struct platform_device *pdev)
 			if (((i + 1) % nand_chip->ecc.bytes) == 0)
 				oob_index++;
 		}
-		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
-							ecclayout->eccbytes;
+		/* include reserved-marker in ecclayout->oobfree calculation */
+		ecclayout->oobfree->offset	= 1 +
+				ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
 		/* software bch library is used for locating errors */
 		nand_chip->ecc.priv		= nand_bch_init(mtd,
 							nand_chip->ecc.size,
@@ -1974,8 +1978,9 @@ static int omap_nand_probe(struct platform_device *pdev)
 		oob_index			= BADBLOCK_MARKER_LENGTH;
 		for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
 			ecclayout->eccpos[i]	= oob_index;
-		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
-							ecclayout->eccbytes;
+		/* reserved marker already included in ecclayout->eccbytes */
+		ecclayout->oobfree->offset	=
+				ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
 		break;
 #else
 		pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");


From linux-mtd at lists.infradead.org  Sun Feb 23 17:59:01 2014
From: linux-mtd at lists.infradead.org (Linux-MTD Mailing List)
Date: Sun, 23 Feb 2014 22:59:01 +0000
Subject: mtd: nand: omap: fix ecclayout to be in sync with u-boot NAND driver
Message-ID: <E1WHi0j-0004i1-8z@bombadil.infradead.org>

Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=eae39cb4934d3daab3ec828c5201c955b2e56af9
Commit:     eae39cb4934d3daab3ec828c5201c955b2e56af9
Parent:     28fa65e643ed7cf753e89db20745e264c41f3682
Author:     Pekon Gupta <pekon at ti.com>
AuthorDate: Mon Feb 17 13:11:23 2014 +0530
Committer:  Brian Norris <computersforpeace at gmail.com>
CommitDate: Sun Feb 23 14:49:56 2014 -0800

    mtd: nand: omap: fix ecclayout to be in sync with u-boot NAND driver
    
    Fixes: commit a919e51161b58ed7e6e663daba99ab7d558808f3
           mtd: nand: omap2: clean-up BCHx_HW and BCHx_SW ECC configurations in device_probe
    
    Fixes ecclayout mismatch introduced in above commit for following ecc-schemes:
     - OMAP_ECC_BCH4_CODE_HW_DETECTION_SW
     - OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
     However, this patch also touches other ecc-schemes as the fix required
     refactoring common code, into ecc-scheme specific code.
    
    This patch aligns ecc-layout for below ecc-schemes as per reference [1],[2],[3]
    
     +---+------------+-------------++-------------+-------------+
     |OOB|BCH8_CODE_HW|BCH8_CODE_HW_||HAM1_CODE_HW |HAM1_CODE_HW |
     |pos|            | DETECTION_SW||(x8 device)  |(x16 device) |
     +---+------------+-------------++-------------+-------------+
     | 0 |BADBLK_MARK | BADBLK_MARK || BADBLK_MARK | BADBLK_MARK |
     | 1 |BADBLK_MARK | BADBLK_MARK || eccpos[0]   | BADBLK_MARK |
     | 2 | eccpos[0]  | eccpos[0]   || eccpos[1]   | eccpos[0]   |
     | 3 | eccpos[1]  | eccpos[1]   || eccpos[2]   | eccpos[1]   |
     | 4 | eccpos[2]  | eccpos[2]   || eccpos[3]   | eccpos[2]   |
     | 5 | eccpos[3]  | eccpos[3]   || eccpos[4]   | eccpos[3]   |
     | 6 | eccpos[4]  | eccpos[4]   || eccpos[5]   | eccpos[4]   |
     | 7 | eccpos[5]  | eccpos[5]   || eccpos[6]   | eccpos[5]   |
     | 8 | eccpos[6]  | eccpos[6]   || eccpos[7]   | eccpos[6]   |
     | 9 | eccpos[7]  | eccpos[7]   || eccpos[8]   | eccpos[7]   |
     |10 | eccpos[8]  | eccpos[8]   || eccpos[9]   | eccpos[8]   |
     |11 | eccpos[9]  | eccpos[9]   || eccpos[10]  | eccpos[9]   |
     |12 | eccpos[10] | eccpos[10]  || eccpos[11]  | eccpos[10]  |
     |13 | eccpos[11] | eccpos[11]  || oobfree[0]  | eccpos[11]  |
     |14 | eccpos[12] | eccpos[12]  || oobfree[1]  | oobfree[0]  |
     |15 | eccpos[13] | <reserved>  || oobfree[2]  | oobfree[1]  |
     +---+------------+-------------++-------------+-------------+
     |16 | eccpos[14] | eccpos[13]  || oobfree[3]  | oobfree[2]  |
     |...| [...]      | [...]       || [...]       | [...]       |
     |56 | eccpos[54] | eccpos[51]  || oobfree[43] | oobfree[42] |
     |57 | eccpos[55] | <reserved>  || oobfree[44] | oobfree[43] |
     +===+============+=============+==============+=============+
     |58 | oobfree[0] | oobfree[0]  || oobfree[45] | oobfree[44] |
     |59 | oobfree[1] | oobfree[1]  || oobfree[46] | oobfree[45] |
     |60 | oobfree[2] | oobfree[2]  || oobfree[47] | oobfree[46] |
     |61 | oobfree[3] | oobfree[3]  || oobfree[48] | oobfree[47] |
     |62 | oobfree[4] | oobfree[4]  || oobfree[49] | oobfree[48] |
     |63 | oobfree[5] | oobfree[5]  || oobfree[50] | oobfree[49] |
     +---+------------+-------------+--------------+-------------+
    
    [1] ecc-layout expected by ROM code, as specified in SoC TRM under:
          Chapter="Initialization"
            Section="Device Initialization by ROM code"
                Sub-Section="Memory Booting"
                    Heading="NAND"
                    Figure="ECC Locations in NAND Spare Areas"
    
    [2] ecc-layout updates in u-boot
        http://lists.denx.de/pipermail/u-boot/2013-November/167551.html
    
    [3] u-boot configurations to match above ecc-layout are documented at
        https://processors.wiki.ti.com/index.php/Linux_Core_NAND_User%27s_Guide
    
    CC: <stable at vger.kernel.org> # 3.13.x+
    Reported-by: Enric Balletbo Serra <eballetbo at iseebcn.com>
    Tested-by: Enric Balletbo i Serra <eballetbo at gmail.com>
    Tested-by: Stefan Roese <sr at denx.de>
    Signed-off-by: Pekon Gupta <pekon at ti.com>
    Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/omap2.c | 31 +++++++++++++++++++++++--------
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index ef4190a..34ef941 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1633,6 +1633,7 @@ static int omap_nand_probe(struct platform_device *pdev)
 	int				i;
 	dma_cap_mask_t			mask;
 	unsigned			sig;
+	unsigned			oob_index;
 	struct resource			*res;
 	struct mtd_part_parser_data	ppdata = {};
 
@@ -1826,9 +1827,11 @@ static int omap_nand_probe(struct platform_device *pdev)
 							(mtd->writesize /
 							nand_chip->ecc.size);
 		if (nand_chip->options & NAND_BUSWIDTH_16)
-			ecclayout->eccpos[0]	= BADBLOCK_MARKER_LENGTH;
+			oob_index		= BADBLOCK_MARKER_LENGTH;
 		else
-			ecclayout->eccpos[0]	= 1;
+			oob_index		= 1;
+		for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+			ecclayout->eccpos[i]	= oob_index;
 		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
 							ecclayout->eccbytes;
 		break;
@@ -1847,7 +1850,12 @@ static int omap_nand_probe(struct platform_device *pdev)
 		ecclayout->eccbytes		= nand_chip->ecc.bytes *
 							(mtd->writesize /
 							nand_chip->ecc.size);
-		ecclayout->eccpos[0]		= BADBLOCK_MARKER_LENGTH;
+		oob_index			= BADBLOCK_MARKER_LENGTH;
+		for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) {
+			ecclayout->eccpos[i] = oob_index;
+			if (((i + 1) % nand_chip->ecc.bytes) == 0)
+				oob_index++;
+		}
 		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
 							ecclayout->eccbytes;
 		/* software bch library is used for locating errors */
@@ -1883,7 +1891,9 @@ static int omap_nand_probe(struct platform_device *pdev)
 		ecclayout->eccbytes		= nand_chip->ecc.bytes *
 							(mtd->writesize /
 							nand_chip->ecc.size);
-		ecclayout->eccpos[0]		= BADBLOCK_MARKER_LENGTH;
+		oob_index			= BADBLOCK_MARKER_LENGTH;
+		for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+			ecclayout->eccpos[i]	= oob_index;
 		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
 							ecclayout->eccbytes;
 		/* This ECC scheme requires ELM H/W block */
@@ -1913,7 +1923,12 @@ static int omap_nand_probe(struct platform_device *pdev)
 		ecclayout->eccbytes		= nand_chip->ecc.bytes *
 							(mtd->writesize /
 							nand_chip->ecc.size);
-		ecclayout->eccpos[0]		= BADBLOCK_MARKER_LENGTH;
+		oob_index			= BADBLOCK_MARKER_LENGTH;
+		for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) {
+			ecclayout->eccpos[i] = oob_index;
+			if (((i + 1) % nand_chip->ecc.bytes) == 0)
+				oob_index++;
+		}
 		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
 							ecclayout->eccbytes;
 		/* software bch library is used for locating errors */
@@ -1956,7 +1971,9 @@ static int omap_nand_probe(struct platform_device *pdev)
 		ecclayout->eccbytes		= nand_chip->ecc.bytes *
 							(mtd->writesize /
 							nand_chip->ecc.size);
-		ecclayout->eccpos[0]		= BADBLOCK_MARKER_LENGTH;
+		oob_index			= BADBLOCK_MARKER_LENGTH;
+		for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+			ecclayout->eccpos[i]	= oob_index;
 		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
 							ecclayout->eccbytes;
 		break;
@@ -1975,8 +1992,6 @@ static int omap_nand_probe(struct platform_device *pdev)
 	/* populate remaining ECC layout data */
 	ecclayout->oobfree->length = mtd->oobsize - (BADBLOCK_MARKER_LENGTH +
 							ecclayout->eccbytes);
-	for (i = 1; i < ecclayout->eccbytes; i++)
-		ecclayout->eccpos[i] = ecclayout->eccpos[0] + i;
 	/* check if NAND device's OOB is enough to store ECC signatures */
 	if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) {
 		pr_err("not enough OOB bytes required = %d, available=%d\n",


From linux-mtd at lists.infradead.org  Sun Feb 23 17:59:01 2014
From: linux-mtd at lists.infradead.org (Linux-MTD Mailing List)
Date: Sun, 23 Feb 2014 22:59:01 +0000
Subject: mtd: nand: omap: fix ecclayout->oobfree->length
Message-ID: <E1WHi0j-0004il-Dc@bombadil.infradead.org>

Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=bb38eefb6858ce16b34716145b9597a5680aa54c
Commit:     bb38eefb6858ce16b34716145b9597a5680aa54c
Parent:     aa6092f9835893290e77c3e24649def49dac1583
Author:     Pekon Gupta <pekon at ti.com>
AuthorDate: Mon Feb 17 13:11:25 2014 +0530
Committer:  Brian Norris <computersforpeace at gmail.com>
CommitDate: Sun Feb 23 14:49:57 2014 -0800

    mtd: nand: omap: fix ecclayout->oobfree->length
    
    This patch excludes reserved-marker byte-position from oobfree->length
    calculation. Thus all bytes from oobfree->offset till end of OOB are free.
    
    CC: <stable at vger.kernel.org> # 3.13.x+
    Signed-off-by: Pekon Gupta <pekon at ti.com>
    Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/omap2.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 58685ab..bf642ce 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1994,9 +1994,8 @@ static int omap_nand_probe(struct platform_device *pdev)
 		goto return_error;
 	}
 
-	/* populate remaining ECC layout data */
-	ecclayout->oobfree->length = mtd->oobsize - (BADBLOCK_MARKER_LENGTH +
-							ecclayout->eccbytes);
+	/* all OOB bytes from oobfree->offset till end off OOB are free */
+	ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
 	/* check if NAND device's OOB is enough to store ECC signatures */
 	if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) {
 		pr_err("not enough OOB bytes required = %d, available=%d\n",


