diff options
author | Pekon Gupta <pekon@ti.com> | 2014-02-17 02:41:24 -0500 |
---|---|---|
committer | Brian Norris <computersforpeace@gmail.com> | 2014-02-23 17:49:57 -0500 |
commit | aa6092f9835893290e77c3e24649def49dac1583 (patch) | |
tree | ec1e53b24298e5e237f608bc8e6fc52c1f4a45b9 | |
parent | eae39cb4934d3daab3ec828c5201c955b2e56af9 (diff) |
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@vger.kernel.org> # 3.13.x+
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>
-rw-r--r-- | drivers/mtd/nand/omap2.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 34ef941e3bfb..58685ab6d865 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) | |||
1832 | oob_index = 1; | 1832 | oob_index = 1; |
1833 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) | 1833 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) |
1834 | ecclayout->eccpos[i] = oob_index; | 1834 | ecclayout->eccpos[i] = oob_index; |
1835 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + | 1835 | /* no reserved-marker in ecclayout for this ecc-scheme */ |
1836 | ecclayout->eccbytes; | 1836 | ecclayout->oobfree->offset = |
1837 | ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; | ||
1837 | break; | 1838 | break; |
1838 | 1839 | ||
1839 | case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: | 1840 | case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: |
@@ -1856,8 +1857,9 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1856 | if (((i + 1) % nand_chip->ecc.bytes) == 0) | 1857 | if (((i + 1) % nand_chip->ecc.bytes) == 0) |
1857 | oob_index++; | 1858 | oob_index++; |
1858 | } | 1859 | } |
1859 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + | 1860 | /* include reserved-marker in ecclayout->oobfree calculation */ |
1860 | ecclayout->eccbytes; | 1861 | ecclayout->oobfree->offset = 1 + |
1862 | ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; | ||
1861 | /* software bch library is used for locating errors */ | 1863 | /* software bch library is used for locating errors */ |
1862 | nand_chip->ecc.priv = nand_bch_init(mtd, | 1864 | nand_chip->ecc.priv = nand_bch_init(mtd, |
1863 | nand_chip->ecc.size, | 1865 | nand_chip->ecc.size, |
@@ -1894,8 +1896,9 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1894 | oob_index = BADBLOCK_MARKER_LENGTH; | 1896 | oob_index = BADBLOCK_MARKER_LENGTH; |
1895 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) | 1897 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) |
1896 | ecclayout->eccpos[i] = oob_index; | 1898 | ecclayout->eccpos[i] = oob_index; |
1897 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + | 1899 | /* reserved marker already included in ecclayout->eccbytes */ |
1898 | ecclayout->eccbytes; | 1900 | ecclayout->oobfree->offset = |
1901 | ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; | ||
1899 | /* This ECC scheme requires ELM H/W block */ | 1902 | /* This ECC scheme requires ELM H/W block */ |
1900 | if (is_elm_present(info, pdata->elm_of_node, BCH4_ECC) < 0) { | 1903 | if (is_elm_present(info, pdata->elm_of_node, BCH4_ECC) < 0) { |
1901 | pr_err("nand: error: could not initialize ELM\n"); | 1904 | pr_err("nand: error: could not initialize ELM\n"); |
@@ -1929,8 +1932,9 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1929 | if (((i + 1) % nand_chip->ecc.bytes) == 0) | 1932 | if (((i + 1) % nand_chip->ecc.bytes) == 0) |
1930 | oob_index++; | 1933 | oob_index++; |
1931 | } | 1934 | } |
1932 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + | 1935 | /* include reserved-marker in ecclayout->oobfree calculation */ |
1933 | ecclayout->eccbytes; | 1936 | ecclayout->oobfree->offset = 1 + |
1937 | ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; | ||
1934 | /* software bch library is used for locating errors */ | 1938 | /* software bch library is used for locating errors */ |
1935 | nand_chip->ecc.priv = nand_bch_init(mtd, | 1939 | nand_chip->ecc.priv = nand_bch_init(mtd, |
1936 | nand_chip->ecc.size, | 1940 | nand_chip->ecc.size, |
@@ -1974,8 +1978,9 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1974 | oob_index = BADBLOCK_MARKER_LENGTH; | 1978 | oob_index = BADBLOCK_MARKER_LENGTH; |
1975 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) | 1979 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) |
1976 | ecclayout->eccpos[i] = oob_index; | 1980 | ecclayout->eccpos[i] = oob_index; |
1977 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + | 1981 | /* reserved marker already included in ecclayout->eccbytes */ |
1978 | ecclayout->eccbytes; | 1982 | ecclayout->oobfree->offset = |
1983 | ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; | ||
1979 | break; | 1984 | break; |
1980 | #else | 1985 | #else |
1981 | pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n"); | 1986 | pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n"); |