]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
mtd: nand: omap: fix ecclayout->oobfree->offset
authorPekon Gupta <pekon@ti.com>
Mon, 17 Feb 2014 07:41:24 +0000 (13:11 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 7 Mar 2014 06:06:25 +0000 (22:06 -0800)
commit aa6092f9835893290e77c3e24649def49dac1583 upstream.

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.

Tested-by: Enric Balletbo i Serra <eballetbo@gmail.com>
Tested-by: Stefan Roese <sr@denx.de>
Signed-off-by: Pekon Gupta <pekon@ti.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/mtd/nand/omap2.c

index 7fb94b1cdfedcd04e10db8fa7085e9e437b0b550..6d6445222f1b0b244c219484478d8efef3feace8 100644 (file)
@@ -1838,8 +1838,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:
@@ -1862,8 +1863,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,
@@ -1900,8 +1902,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");
@@ -1935,8 +1938,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,
@@ -1980,8 +1984,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");