aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/onenand
diff options
context:
space:
mode:
authorAdrian Hunter <ext-adrian.hunter@nokia.com>2007-11-06 02:17:25 -0500
committerDavid Woodhouse <dwmw2@infradead.org>2007-11-26 08:16:29 -0500
commit5f4d47d5d1060a93be83e33a167a53a7f8c08b20 (patch)
treee3bd4b358774b59af30c8d23241cec19e29e9d76 /drivers/mtd/onenand
parentb1c9c9be6da010510459aca93f5754efb19695ff (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>
Diffstat (limited to 'drivers/mtd/onenand')
-rw-r--r--drivers/mtd/onenand/onenand_base.c32
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/**