diff options
author | Adrian Hunter <ext-adrian.hunter@nokia.com> | 2007-11-06 02:17:25 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2007-11-26 08:16:29 -0500 |
commit | 5f4d47d5d1060a93be83e33a167a53a7f8c08b20 (patch) | |
tree | e3bd4b358774b59af30c8d23241cec19e29e9d76 | |
parent | b1c9c9be6da010510459aca93f5754efb19695ff (diff) |
[MTD] [OneNAND] Do not stop reading for ECC errors
When an ECC error occurs, the read should be completed
anyway before returning -EBADMSG. Returning -EBADMSG
straight away is incorrect.
Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r-- | drivers/mtd/onenand/onenand_base.c | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 1b0b32011415..ed9f9c061ac5 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
@@ -855,6 +855,8 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, | |||
855 | this->command(mtd, ONENAND_CMD_READ, from, writesize); | 855 | this->command(mtd, ONENAND_CMD_READ, from, writesize); |
856 | ret = this->wait(mtd, FL_READING); | 856 | ret = this->wait(mtd, FL_READING); |
857 | onenand_update_bufferram(mtd, from, !ret); | 857 | onenand_update_bufferram(mtd, from, !ret); |
858 | if (ret == -EBADMSG) | ||
859 | ret = 0; | ||
858 | } | 860 | } |
859 | } | 861 | } |
860 | 862 | ||
@@ -913,6 +915,8 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, | |||
913 | /* Now wait for load */ | 915 | /* Now wait for load */ |
914 | ret = this->wait(mtd, FL_READING); | 916 | ret = this->wait(mtd, FL_READING); |
915 | onenand_update_bufferram(mtd, from, !ret); | 917 | onenand_update_bufferram(mtd, from, !ret); |
918 | if (ret == -EBADMSG) | ||
919 | ret = 0; | ||
916 | } | 920 | } |
917 | 921 | ||
918 | /* | 922 | /* |
@@ -923,12 +927,12 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, | |||
923 | ops->retlen = read; | 927 | ops->retlen = read; |
924 | ops->oobretlen = oobread; | 928 | ops->oobretlen = oobread; |
925 | 929 | ||
926 | if (mtd->ecc_stats.failed - stats.failed) | ||
927 | return -EBADMSG; | ||
928 | |||
929 | if (ret) | 930 | if (ret) |
930 | return ret; | 931 | return ret; |
931 | 932 | ||
933 | if (mtd->ecc_stats.failed - stats.failed) | ||
934 | return -EBADMSG; | ||
935 | |||
932 | return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; | 936 | return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; |
933 | } | 937 | } |
934 | 938 | ||
@@ -944,6 +948,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, | |||
944 | struct mtd_oob_ops *ops) | 948 | struct mtd_oob_ops *ops) |
945 | { | 949 | { |
946 | struct onenand_chip *this = mtd->priv; | 950 | struct onenand_chip *this = mtd->priv; |
951 | struct mtd_ecc_stats stats; | ||
947 | int read = 0, thislen, column, oobsize; | 952 | int read = 0, thislen, column, oobsize; |
948 | size_t len = ops->ooblen; | 953 | size_t len = ops->ooblen; |
949 | mtd_oob_mode_t mode = ops->mode; | 954 | mtd_oob_mode_t mode = ops->mode; |
@@ -977,6 +982,8 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, | |||
977 | return -EINVAL; | 982 | return -EINVAL; |
978 | } | 983 | } |
979 | 984 | ||
985 | stats = mtd->ecc_stats; | ||
986 | |||
980 | while (read < len) { | 987 | while (read < len) { |
981 | cond_resched(); | 988 | cond_resched(); |
982 | 989 | ||
@@ -988,18 +995,16 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, | |||
988 | onenand_update_bufferram(mtd, from, 0); | 995 | onenand_update_bufferram(mtd, from, 0); |
989 | 996 | ||
990 | ret = this->wait(mtd, FL_READING); | 997 | ret = this->wait(mtd, FL_READING); |
991 | /* First copy data and check return value for ECC handling */ | 998 | if (ret && ret != -EBADMSG) { |
999 | printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret); | ||
1000 | break; | ||
1001 | } | ||
992 | 1002 | ||
993 | if (mode == MTD_OOB_AUTO) | 1003 | if (mode == MTD_OOB_AUTO) |
994 | onenand_transfer_auto_oob(mtd, buf, column, thislen); | 1004 | onenand_transfer_auto_oob(mtd, buf, column, thislen); |
995 | else | 1005 | else |
996 | this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); | 1006 | this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); |
997 | 1007 | ||
998 | if (ret) { | ||
999 | printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret); | ||
1000 | break; | ||
1001 | } | ||
1002 | |||
1003 | read += thislen; | 1008 | read += thislen; |
1004 | 1009 | ||
1005 | if (read == len) | 1010 | if (read == len) |
@@ -1016,7 +1021,14 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, | |||
1016 | } | 1021 | } |
1017 | 1022 | ||
1018 | ops->oobretlen = read; | 1023 | ops->oobretlen = read; |
1019 | return ret; | 1024 | |
1025 | if (ret) | ||
1026 | return ret; | ||
1027 | |||
1028 | if (mtd->ecc_stats.failed - stats.failed) | ||
1029 | return -EBADMSG; | ||
1030 | |||
1031 | return 0; | ||
1020 | } | 1032 | } |
1021 | 1033 | ||
1022 | /** | 1034 | /** |