Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[MTD] OneNAND: Error message printing and bad block scan erros

Provide the bad block scan with its own read function so that important error
messages that are not from the the bad block scan, can always be printed.

Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>

+155 -30
+136 -21
drivers/mtd/onenand/onenand_base.c
··· 304 304 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); 305 305 306 306 if (ctrl & ONENAND_CTRL_ERROR) { 307 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl); 307 + printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n", ctrl); 308 308 if (ctrl & ONENAND_CTRL_LOCK) 309 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error.\n"); 309 + printk(KERN_ERR "onenand_wait: it's locked error.\n"); 310 310 return ctrl; 311 311 } 312 312 313 313 if (interrupt & ONENAND_INT_READ) { 314 314 int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); 315 315 if (ecc) { 316 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc); 316 + printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc); 317 317 if (ecc & ONENAND_ECC_2BIT_ALL) { 318 318 mtd->ecc_stats.failed++; 319 319 return ecc; ··· 703 703 704 704 /* Do not allow reads past end of device */ 705 705 if ((from + len) > mtd->size) { 706 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: Attempt read beyond end of device\n"); 706 + printk(KERN_ERR "onenand_read: Attempt read beyond end of device\n"); 707 707 *retlen = 0; 708 708 return -EINVAL; 709 709 } ··· 834 834 * 835 835 * OneNAND read out-of-band data from the spare area 836 836 */ 837 - int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len, 837 + static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len, 838 838 size_t *retlen, u_char *buf, mtd_oob_mode_t mode) 839 839 { 840 840 struct onenand_chip *this = mtd->priv; ··· 854 854 column = from & (mtd->oobsize - 1); 855 855 856 856 if (unlikely(column >= oobsize)) { 857 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: Attempted to start read outside oob\n"); 857 + printk(KERN_ERR "onenand_read_oob: Attempted to start read outside oob\n"); 858 858 return -EINVAL; 859 859 } 860 860 ··· 862 862 if (unlikely(from >= mtd->size || 863 863 column + len > ((mtd->size >> this->page_shift) - 864 864 (from >> this->page_shift)) * oobsize)) { 865 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: Attempted to read beyond end of device\n"); 865 + printk(KERN_ERR "onenand_read_oob: Attempted to read beyond end of device\n"); 866 866 return -EINVAL; 867 867 } 868 868 ··· 888 888 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); 889 889 890 890 if (ret) { 891 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = 0x%x\n", ret); 891 + printk(KERN_ERR "onenand_read_oob: read failed = 0x%x\n", ret); 892 892 break; 893 893 } 894 894 ··· 934 934 } 935 935 return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->ooblen, 936 936 &ops->oobretlen, ops->oobbuf, ops->mode); 937 + } 938 + 939 + /** 940 + * onenand_bbt_wait - [DEFAULT] wait until the command is done 941 + * @param mtd MTD device structure 942 + * @param state state to select the max. timeout value 943 + * 944 + * Wait for command done. 945 + */ 946 + static int onenand_bbt_wait(struct mtd_info *mtd, int state) 947 + { 948 + struct onenand_chip *this = mtd->priv; 949 + unsigned long timeout; 950 + unsigned int interrupt; 951 + unsigned int ctrl; 952 + 953 + /* The 20 msec is enough */ 954 + timeout = jiffies + msecs_to_jiffies(20); 955 + while (time_before(jiffies, timeout)) { 956 + interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); 957 + if (interrupt & ONENAND_INT_MASTER) 958 + break; 959 + } 960 + /* To get correct interrupt status in timeout case */ 961 + interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); 962 + ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); 963 + 964 + if (ctrl & ONENAND_CTRL_ERROR) { 965 + printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl); 966 + /* Initial bad block case */ 967 + if (ctrl & ONENAND_CTRL_LOAD) 968 + return ONENAND_BBT_READ_ERROR; 969 + return ONENAND_BBT_READ_FATAL_ERROR; 970 + } 971 + 972 + if (interrupt & ONENAND_INT_READ) { 973 + int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); 974 + if (ecc & ONENAND_ECC_2BIT_ALL) 975 + return ONENAND_BBT_READ_ERROR; 976 + } else { 977 + printk(KERN_ERR "onenand_bbt_wait: read timeout!" 978 + "ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt); 979 + return ONENAND_BBT_READ_FATAL_ERROR; 980 + } 981 + 982 + return 0; 983 + } 984 + 985 + /** 986 + * onenand_bbt_read_oob - [MTD Interface] OneNAND read out-of-band for bbt scan 987 + * @param mtd MTD device structure 988 + * @param from offset to read from 989 + * @param @ops oob operation description structure 990 + * 991 + * OneNAND read out-of-band data from the spare area for bbt scan 992 + */ 993 + int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, 994 + struct mtd_oob_ops *ops) 995 + { 996 + struct onenand_chip *this = mtd->priv; 997 + int read = 0, thislen, column; 998 + int ret = 0; 999 + size_t len = ops->ooblen; 1000 + u_char *buf = ops->oobbuf; 1001 + 1002 + DEBUG(MTD_DEBUG_LEVEL3, "onenand_bbt_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, len); 1003 + 1004 + /* Initialize return value */ 1005 + ops->oobretlen = 0; 1006 + 1007 + /* Do not allow reads past end of device */ 1008 + if (unlikely((from + len) > mtd->size)) { 1009 + printk(KERN_ERR "onenand_bbt_read_oob: Attempt read beyond end of device\n"); 1010 + return ONENAND_BBT_READ_FATAL_ERROR; 1011 + } 1012 + 1013 + /* Grab the lock and see if the device is available */ 1014 + onenand_get_device(mtd, FL_READING); 1015 + 1016 + column = from & (mtd->oobsize - 1); 1017 + 1018 + while (read < len) { 1019 + cond_resched(); 1020 + 1021 + thislen = mtd->oobsize - column; 1022 + thislen = min_t(int, thislen, len); 1023 + 1024 + this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize); 1025 + 1026 + onenand_update_bufferram(mtd, from, 0); 1027 + 1028 + ret = onenand_bbt_wait(mtd, FL_READING); 1029 + if (ret) 1030 + break; 1031 + 1032 + this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); 1033 + read += thislen; 1034 + if (read == len) 1035 + break; 1036 + 1037 + buf += thislen; 1038 + 1039 + /* Read more? */ 1040 + if (read < len) { 1041 + /* Update Page size */ 1042 + from += mtd->writesize; 1043 + column = 0; 1044 + } 1045 + } 1046 + 1047 + /* Deselect and wake up anyone waiting on the device */ 1048 + onenand_release_device(mtd); 1049 + 1050 + ops->oobretlen = read; 1051 + return ret; 937 1052 } 938 1053 939 1054 #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE ··· 1155 1040 1156 1041 /* Do not allow writes past end of device */ 1157 1042 if (unlikely((to + len) > mtd->size)) { 1158 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt write to past end of device\n"); 1043 + printk(KERN_ERR "onenand_write: Attempt write to past end of device\n"); 1159 1044 return -EINVAL; 1160 1045 } 1161 1046 1162 1047 /* Reject writes, which are not page aligned */ 1163 1048 if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) { 1164 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt to write not page aligned data\n"); 1049 + printk(KERN_ERR "onenand_write: Attempt to write not page aligned data\n"); 1165 1050 return -EINVAL; 1166 1051 } 1167 1052 ··· 1198 1083 onenand_update_bufferram(mtd, to, !ret && !subpage); 1199 1084 1200 1085 if (ret) { 1201 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret); 1086 + printk(KERN_ERR "onenand_write: write filaed %d\n", ret); 1202 1087 break; 1203 1088 } 1204 1089 1205 1090 /* Only check verify write turn on */ 1206 1091 ret = onenand_verify(mtd, (u_char *) wbuf, to, thislen); 1207 1092 if (ret) { 1208 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret); 1093 + printk(KERN_ERR "onenand_write: verify failed %d\n", ret); 1209 1094 break; 1210 1095 } 1211 1096 ··· 1295 1180 column = to & (mtd->oobsize - 1); 1296 1181 1297 1182 if (unlikely(column >= oobsize)) { 1298 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: Attempted to start write outside oob\n"); 1183 + printk(KERN_ERR "onenand_write_oob: Attempted to start write outside oob\n"); 1299 1184 return -EINVAL; 1300 1185 } 1301 1186 1302 1187 /* For compatibility with NAND: Do not allow write past end of page */ 1303 1188 if (column + len > oobsize) { 1304 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: " 1189 + printk(KERN_ERR "onenand_write_oob: " 1305 1190 "Attempt to write past end of page\n"); 1306 1191 return -EINVAL; 1307 1192 } ··· 1310 1195 if (unlikely(to >= mtd->size || 1311 1196 column + len > ((mtd->size >> this->page_shift) - 1312 1197 (to >> this->page_shift)) * oobsize)) { 1313 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: Attempted to write past end of device\n"); 1198 + printk(KERN_ERR "onenand_write_oob: Attempted to write past end of device\n"); 1314 1199 return -EINVAL; 1315 1200 } 1316 1201 ··· 1340 1225 1341 1226 ret = this->wait(mtd, FL_WRITING); 1342 1227 if (ret) { 1343 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: write failed %d\n", ret); 1228 + printk(KERN_ERR "onenand_write_oob: write failed %d\n", ret); 1344 1229 break; 1345 1230 } 1346 1231 1347 1232 ret = onenand_verify_oob(mtd, this->page_buf, to); 1348 1233 if (ret) { 1349 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: verify failed %d\n", ret); 1234 + printk(KERN_ERR "onenand_write_oob: verify failed %d\n", ret); 1350 1235 break; 1351 1236 } 1352 1237 ··· 1429 1314 1430 1315 /* Start address must align on block boundary */ 1431 1316 if (unlikely(instr->addr & (block_size - 1))) { 1432 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Unaligned address\n"); 1317 + printk(KERN_ERR "onenand_erase: Unaligned address\n"); 1433 1318 return -EINVAL; 1434 1319 } 1435 1320 1436 1321 /* Length must align on block boundary */ 1437 1322 if (unlikely(instr->len & (block_size - 1))) { 1438 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Length not block aligned\n"); 1323 + printk(KERN_ERR "onenand_erase: Length not block aligned\n"); 1439 1324 return -EINVAL; 1440 1325 } 1441 1326 1442 1327 /* Do not allow erase past end of device */ 1443 1328 if (unlikely((instr->len + instr->addr) > mtd->size)) { 1444 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Erase past end of device\n"); 1329 + printk(KERN_ERR "onenand_erase: Erase past end of device\n"); 1445 1330 return -EINVAL; 1446 1331 } 1447 1332 ··· 1471 1356 ret = this->wait(mtd, FL_ERASING); 1472 1357 /* Check, if it is write protected */ 1473 1358 if (ret) { 1474 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift)); 1359 + printk(KERN_ERR "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift)); 1475 1360 instr->state = MTD_ERASE_FAILED; 1476 1361 instr->fail_addr = addr; 1477 1362 goto erase_exit;
+12 -9
drivers/mtd/onenand/onenand_bbt.c
··· 17 17 #include <linux/mtd/onenand.h> 18 18 #include <linux/mtd/compatmac.h> 19 19 20 - extern int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len, 21 - size_t *retlen, u_char *buf, mtd_oob_mode_t mode); 20 + extern int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, 21 + struct mtd_oob_ops *ops); 22 22 23 23 /** 24 24 * check_short_pattern - [GENERIC] check if a pattern is in the buffer ··· 65 65 int startblock; 66 66 loff_t from; 67 67 size_t readlen, ooblen; 68 + struct mtd_oob_ops ops; 68 69 69 70 printk(KERN_INFO "Scanning device for bad blocks\n"); 70 71 ··· 83 82 startblock = 0; 84 83 from = 0; 85 84 85 + ops.mode = MTD_OOB_PLACE; 86 + ops.ooblen = readlen; 87 + ops.oobbuf = buf; 88 + ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0; 89 + 86 90 for (i = startblock; i < numblocks; ) { 87 91 int ret; 88 92 89 93 for (j = 0; j < len; j++) { 90 - size_t retlen; 91 - 92 94 /* No need to read pages fully, 93 95 * just read required OOB bytes */ 94 - ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs, 95 - readlen, &retlen, &buf[0], MTD_OOB_PLACE); 96 + ret = onenand_bbt_read_oob(mtd, from + j * mtd->writesize + bd->offs, &ops); 96 97 97 98 /* If it is a initial bad block, just ignore it */ 98 - if (ret && !(ret & ONENAND_CTRL_LOAD)) 99 - return ret; 99 + if (ret == ONENAND_BBT_READ_FATAL_ERROR) 100 + return -EIO; 100 101 101 - if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) { 102 + if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) { 102 103 bbm->bbt[i >> 3] |= 0x03 << (i & 0x6); 103 104 printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n", 104 105 i >> 1, (unsigned int) from);
+7
include/linux/mtd/bbm.h
··· 92 92 */ 93 93 #define ONENAND_BADBLOCK_POS 0 94 94 95 + /* 96 + * Bad block scanning errors 97 + */ 98 + #define ONENAND_BBT_READ_ERROR 1 99 + #define ONENAND_BBT_READ_ECC_ERROR 2 100 + #define ONENAND_BBT_READ_FATAL_ERROR 4 101 + 95 102 /** 96 103 * struct bbm_info - [GENERIC] Bad Block Table data structure 97 104 * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry