Commit 5f4d47d5d1060a93be83e33a167a53a7f8c08b20
Committed by
David Woodhouse
1 parent
b1c9c9be6d
Exists in
master
and in
7 other branches
[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>
Showing 1 changed file with 22 additions and 10 deletions Side-by-side Diff
drivers/mtd/onenand/onenand_base.c
... | ... | @@ -855,6 +855,8 @@ |
855 | 855 | this->command(mtd, ONENAND_CMD_READ, from, writesize); |
856 | 856 | ret = this->wait(mtd, FL_READING); |
857 | 857 | onenand_update_bufferram(mtd, from, !ret); |
858 | + if (ret == -EBADMSG) | |
859 | + ret = 0; | |
858 | 860 | } |
859 | 861 | } |
860 | 862 | |
... | ... | @@ -913,6 +915,8 @@ |
913 | 915 | /* Now wait for load */ |
914 | 916 | ret = this->wait(mtd, FL_READING); |
915 | 917 | onenand_update_bufferram(mtd, from, !ret); |
918 | + if (ret == -EBADMSG) | |
919 | + ret = 0; | |
916 | 920 | } |
917 | 921 | |
918 | 922 | /* |
919 | 923 | |
... | ... | @@ -923,12 +927,12 @@ |
923 | 927 | ops->retlen = read; |
924 | 928 | ops->oobretlen = oobread; |
925 | 929 | |
926 | - if (mtd->ecc_stats.failed - stats.failed) | |
927 | - return -EBADMSG; | |
928 | - | |
929 | 930 | if (ret) |
930 | 931 | return ret; |
931 | 932 | |
933 | + if (mtd->ecc_stats.failed - stats.failed) | |
934 | + return -EBADMSG; | |
935 | + | |
932 | 936 | return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; |
933 | 937 | } |
934 | 938 | |
... | ... | @@ -944,6 +948,7 @@ |
944 | 948 | struct mtd_oob_ops *ops) |
945 | 949 | { |
946 | 950 | struct onenand_chip *this = mtd->priv; |
951 | + struct mtd_ecc_stats stats; | |
947 | 952 | int read = 0, thislen, column, oobsize; |
948 | 953 | size_t len = ops->ooblen; |
949 | 954 | mtd_oob_mode_t mode = ops->mode; |
... | ... | @@ -977,6 +982,8 @@ |
977 | 982 | return -EINVAL; |
978 | 983 | } |
979 | 984 | |
985 | + stats = mtd->ecc_stats; | |
986 | + | |
980 | 987 | while (read < len) { |
981 | 988 | cond_resched(); |
982 | 989 | |
983 | 990 | |
... | ... | @@ -988,18 +995,16 @@ |
988 | 995 | onenand_update_bufferram(mtd, from, 0); |
989 | 996 | |
990 | 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 | 1003 | if (mode == MTD_OOB_AUTO) |
994 | 1004 | onenand_transfer_auto_oob(mtd, buf, column, thislen); |
995 | 1005 | else |
996 | 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 | 1008 | read += thislen; |
1004 | 1009 | |
1005 | 1010 | if (read == len) |
... | ... | @@ -1016,7 +1021,14 @@ |
1016 | 1021 | } |
1017 | 1022 | |
1018 | 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 | /** |