aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2007-09-21 12:35:21 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2007-09-23 14:58:52 -0400
commit49dc08eeda707f59019814fe07a2b17979348002 (patch)
tree8d7a38e54d6f07e42b953478437fa6a535f4e723
parent0bac5111cc00b70460dd8ba8340522e1f0d79f05 (diff)
[MTD] [OneNAND] fix numerous races
This patch make the OneNAND driver much less racy. It fixes our "onenand_wait: read timeout!" heisenbugs. The reason of these bugs was that the driver did not lock the chip when accessing OTP, and it screwed up OneNAND state when the OTP was read while JFFS2 was doing FS checking. This patch also fixes other races I spotted: 1. BBT was not protected 2. Access to ecc_stats was not protected Now the chip is locked when BBT is accessed. To fix all of these I basically split all interface functions on 'function()' and 'function_nolock()' parts. I tested this patch on N800 hardware - it fixes our problems. But I tested a little different version because our OneNAND codebase is slightly out-of-date. But it should be OK. This patch also includes the prin fixes I posted before. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r--drivers/mtd/onenand/onenand_base.c170
1 files changed, 95 insertions, 75 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 40d8d6ff626b..85a97198bee3 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -333,12 +333,14 @@ static int onenand_wait(struct mtd_info *mtd, int state)
333 if (interrupt & ONENAND_INT_READ) { 333 if (interrupt & ONENAND_INT_READ) {
334 int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); 334 int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
335 if (ecc) { 335 if (ecc) {
336 printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc);
337 if (ecc & ONENAND_ECC_2BIT_ALL) { 336 if (ecc & ONENAND_ECC_2BIT_ALL) {
337 printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc);
338 mtd->ecc_stats.failed++; 338 mtd->ecc_stats.failed++;
339 return ecc; 339 return ecc;
340 } else if (ecc & ONENAND_ECC_1BIT_ALL) 340 } else if (ecc & ONENAND_ECC_1BIT_ALL) {
341 printk(KERN_INFO "onenand_wait: correctable ECC error = 0x%04x\n", ecc);
341 mtd->ecc_stats.corrected++; 342 mtd->ecc_stats.corrected++;
343 }
342 } 344 }
343 } else if (state == FL_READING) { 345 } else if (state == FL_READING) {
344 printk(KERN_ERR "onenand_wait: read timeout! ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt); 346 printk(KERN_ERR "onenand_wait: read timeout! ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
@@ -805,14 +807,14 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col
805} 807}
806 808
807/** 809/**
808 * onenand_read_ops - [OneNAND Interface] OneNAND read main and/or out-of-band 810 * onenand_read_ops_nolock - [OneNAND Interface] OneNAND read main and/or out-of-band
809 * @param mtd MTD device structure 811 * @param mtd MTD device structure
810 * @param from offset to read from 812 * @param from offset to read from
811 * @param ops: oob operation description structure 813 * @param ops: oob operation description structure
812 * 814 *
813 * OneNAND read main and/or out-of-band data 815 * OneNAND read main and/or out-of-band data
814 */ 816 */
815static int onenand_read_ops(struct mtd_info *mtd, loff_t from, 817static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
816 struct mtd_oob_ops *ops) 818 struct mtd_oob_ops *ops)
817{ 819{
818 struct onenand_chip *this = mtd->priv; 820 struct onenand_chip *this = mtd->priv;
@@ -826,7 +828,7 @@ static int onenand_read_ops(struct mtd_info *mtd, loff_t from,
826 int ret = 0, boundary = 0; 828 int ret = 0, boundary = 0;
827 int writesize = this->writesize; 829 int writesize = this->writesize;
828 830
829 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ops: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); 831 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
830 832
831 if (ops->mode == MTD_OOB_AUTO) 833 if (ops->mode == MTD_OOB_AUTO)
832 oobsize = this->ecclayout->oobavail; 834 oobsize = this->ecclayout->oobavail;
@@ -837,15 +839,12 @@ static int onenand_read_ops(struct mtd_info *mtd, loff_t from,
837 839
838 /* Do not allow reads past end of device */ 840 /* Do not allow reads past end of device */
839 if ((from + len) > mtd->size) { 841 if ((from + len) > mtd->size) {
840 printk(KERN_ERR "onenand_read_ops: Attempt read beyond end of device\n"); 842 printk(KERN_ERR "onenand_read_ops_nolock: Attempt read beyond end of device\n");
841 ops->retlen = 0; 843 ops->retlen = 0;
842 ops->oobretlen = 0; 844 ops->oobretlen = 0;
843 return -EINVAL; 845 return -EINVAL;
844 } 846 }
845 847
846 /* Grab the lock and see if the device is available */
847 onenand_get_device(mtd, FL_READING);
848
849 stats = mtd->ecc_stats; 848 stats = mtd->ecc_stats;
850 849
851 /* Read-while-load method */ 850 /* Read-while-load method */
@@ -916,9 +915,6 @@ static int onenand_read_ops(struct mtd_info *mtd, loff_t from,
916 onenand_update_bufferram(mtd, from, !ret); 915 onenand_update_bufferram(mtd, from, !ret);
917 } 916 }
918 917
919 /* Deselect and wake up anyone waiting on the device */
920 onenand_release_device(mtd);
921
922 /* 918 /*
923 * Return success, if no ECC failures, else -EBADMSG 919 * Return success, if no ECC failures, else -EBADMSG
924 * fs driver will take care of that, because 920 * fs driver will take care of that, because
@@ -937,14 +933,14 @@ static int onenand_read_ops(struct mtd_info *mtd, loff_t from,
937} 933}
938 934
939/** 935/**
940 * onenand_do_read_oob - [MTD Interface] OneNAND read out-of-band 936 * onenand_read_oob_nolock - [MTD Interface] OneNAND read out-of-band
941 * @param mtd MTD device structure 937 * @param mtd MTD device structure
942 * @param from offset to read from 938 * @param from offset to read from
943 * @param ops: oob operation description structure 939 * @param ops: oob operation description structure
944 * 940 *
945 * OneNAND read out-of-band data from the spare area 941 * OneNAND read out-of-band data from the spare area
946 */ 942 */
947static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, 943static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
948 struct mtd_oob_ops *ops) 944 struct mtd_oob_ops *ops)
949{ 945{
950 struct onenand_chip *this = mtd->priv; 946 struct onenand_chip *this = mtd->priv;
@@ -956,7 +952,7 @@ static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from,
956 952
957 from += ops->ooboffs; 953 from += ops->ooboffs;
958 954
959 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); 955 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
960 956
961 /* Initialize return length value */ 957 /* Initialize return length value */
962 ops->oobretlen = 0; 958 ops->oobretlen = 0;
@@ -969,7 +965,7 @@ static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from,
969 column = from & (mtd->oobsize - 1); 965 column = from & (mtd->oobsize - 1);
970 966
971 if (unlikely(column >= oobsize)) { 967 if (unlikely(column >= oobsize)) {
972 printk(KERN_ERR "onenand_read_oob: Attempted to start read outside oob\n"); 968 printk(KERN_ERR "onenand_read_oob_nolock: Attempted to start read outside oob\n");
973 return -EINVAL; 969 return -EINVAL;
974 } 970 }
975 971
@@ -977,13 +973,10 @@ static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from,
977 if (unlikely(from >= mtd->size || 973 if (unlikely(from >= mtd->size ||
978 column + len > ((mtd->size >> this->page_shift) - 974 column + len > ((mtd->size >> this->page_shift) -
979 (from >> this->page_shift)) * oobsize)) { 975 (from >> this->page_shift)) * oobsize)) {
980 printk(KERN_ERR "onenand_read_oob: Attempted to read beyond end of device\n"); 976 printk(KERN_ERR "onenand_read_oob_nolock: Attempted to read beyond end of device\n");
981 return -EINVAL; 977 return -EINVAL;
982 } 978 }
983 979
984 /* Grab the lock and see if the device is available */
985 onenand_get_device(mtd, FL_READING);
986
987 while (read < len) { 980 while (read < len) {
988 cond_resched(); 981 cond_resched();
989 982
@@ -1003,7 +996,7 @@ static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from,
1003 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); 996 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
1004 997
1005 if (ret) { 998 if (ret) {
1006 printk(KERN_ERR "onenand_read_oob: read failed = 0x%x\n", ret); 999 printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret);
1007 break; 1000 break;
1008 } 1001 }
1009 1002
@@ -1022,9 +1015,6 @@ static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from,
1022 } 1015 }
1023 } 1016 }
1024 1017
1025 /* Deselect and wake up anyone waiting on the device */
1026 onenand_release_device(mtd);
1027
1028 ops->oobretlen = read; 1018 ops->oobretlen = read;
1029 return ret; 1019 return ret;
1030} 1020}
@@ -1050,9 +1040,11 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
1050 }; 1040 };
1051 int ret; 1041 int ret;
1052 1042
1053 ret = onenand_read_ops(mtd, from, &ops); 1043 onenand_get_device(mtd, FL_READING);
1054 *retlen = ops.retlen; 1044 ret = onenand_read_ops_nolock(mtd, from, &ops);
1045 onenand_release_device(mtd);
1055 1046
1047 *retlen = ops.retlen;
1056 return ret; 1048 return ret;
1057} 1049}
1058 1050
@@ -1067,6 +1059,8 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
1067static int onenand_read_oob(struct mtd_info *mtd, loff_t from, 1059static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
1068 struct mtd_oob_ops *ops) 1060 struct mtd_oob_ops *ops)
1069{ 1061{
1062 int ret;
1063
1070 switch (ops->mode) { 1064 switch (ops->mode) {
1071 case MTD_OOB_PLACE: 1065 case MTD_OOB_PLACE:
1072 case MTD_OOB_AUTO: 1066 case MTD_OOB_AUTO:
@@ -1077,10 +1071,14 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
1077 return -EINVAL; 1071 return -EINVAL;
1078 } 1072 }
1079 1073
1074 onenand_get_device(mtd, FL_READING);
1080 if (ops->datbuf) 1075 if (ops->datbuf)
1081 return onenand_read_ops(mtd, from, ops); 1076 ret = onenand_read_ops_nolock(mtd, from, ops);
1077 else
1078 ret = onenand_read_oob_nolock(mtd, from, ops);
1079 onenand_release_device(mtd);
1082 1080
1083 return onenand_do_read_oob(mtd, from, ops); 1081 return ret;
1084} 1082}
1085 1083
1086/** 1084/**
@@ -1317,14 +1315,14 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
1317} 1315}
1318 1316
1319/** 1317/**
1320 * onenand_write_ops - [OneNAND Interface] write main and/or out-of-band 1318 * onenand_write_ops_nolock - [OneNAND Interface] write main and/or out-of-band
1321 * @param mtd MTD device structure 1319 * @param mtd MTD device structure
1322 * @param to offset to write to 1320 * @param to offset to write to
1323 * @param ops oob operation description structure 1321 * @param ops oob operation description structure
1324 * 1322 *
1325 * Write main and/or oob with ECC 1323 * Write main and/or oob with ECC
1326 */ 1324 */
1327static int onenand_write_ops(struct mtd_info *mtd, loff_t to, 1325static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
1328 struct mtd_oob_ops *ops) 1326 struct mtd_oob_ops *ops)
1329{ 1327{
1330 struct onenand_chip *this = mtd->priv; 1328 struct onenand_chip *this = mtd->priv;
@@ -1337,7 +1335,7 @@ static int onenand_write_ops(struct mtd_info *mtd, loff_t to,
1337 u_char *oobbuf; 1335 u_char *oobbuf;
1338 int ret = 0; 1336 int ret = 0;
1339 1337
1340 DEBUG(MTD_DEBUG_LEVEL3, "onenand_write: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); 1338 DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ops_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
1341 1339
1342 /* Initialize retlen, in case of early exit */ 1340 /* Initialize retlen, in case of early exit */
1343 ops->retlen = 0; 1341 ops->retlen = 0;
@@ -1345,13 +1343,13 @@ static int onenand_write_ops(struct mtd_info *mtd, loff_t to,
1345 1343
1346 /* Do not allow writes past end of device */ 1344 /* Do not allow writes past end of device */
1347 if (unlikely((to + len) > mtd->size)) { 1345 if (unlikely((to + len) > mtd->size)) {
1348 printk(KERN_ERR "onenand_write: Attempt write to past end of device\n"); 1346 printk(KERN_ERR "onenand_write_ops_nolock: Attempt write to past end of device\n");
1349 return -EINVAL; 1347 return -EINVAL;
1350 } 1348 }
1351 1349
1352 /* Reject writes, which are not page aligned */ 1350 /* Reject writes, which are not page aligned */
1353 if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) { 1351 if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
1354 printk(KERN_ERR "onenand_write: Attempt to write not page aligned data\n"); 1352 printk(KERN_ERR "onenand_write_ops_nolock: Attempt to write not page aligned data\n");
1355 return -EINVAL; 1353 return -EINVAL;
1356 } 1354 }
1357 1355
@@ -1364,9 +1362,6 @@ static int onenand_write_ops(struct mtd_info *mtd, loff_t to,
1364 1362
1365 column = to & (mtd->writesize - 1); 1363 column = to & (mtd->writesize - 1);
1366 1364
1367 /* Grab the lock and see if the device is available */
1368 onenand_get_device(mtd, FL_WRITING);
1369
1370 /* Loop until all data write */ 1365 /* Loop until all data write */
1371 while (written < len) { 1366 while (written < len) {
1372 u_char *wbuf = (u_char *) buf; 1367 u_char *wbuf = (u_char *) buf;
@@ -1419,14 +1414,14 @@ static int onenand_write_ops(struct mtd_info *mtd, loff_t to,
1419 } 1414 }
1420 1415
1421 if (ret) { 1416 if (ret) {
1422 printk(KERN_ERR "onenand_write: write filaed %d\n", ret); 1417 printk(KERN_ERR "onenand_write_ops_nolock: write filaed %d\n", ret);
1423 break; 1418 break;
1424 } 1419 }
1425 1420
1426 /* Only check verify write turn on */ 1421 /* Only check verify write turn on */
1427 ret = onenand_verify(mtd, (u_char *) wbuf, to, thislen); 1422 ret = onenand_verify(mtd, (u_char *) wbuf, to, thislen);
1428 if (ret) { 1423 if (ret) {
1429 printk(KERN_ERR "onenand_write: verify failed %d\n", ret); 1424 printk(KERN_ERR "onenand_write_ops_nolock: verify failed %d\n", ret);
1430 break; 1425 break;
1431 } 1426 }
1432 1427
@@ -1450,7 +1445,7 @@ static int onenand_write_ops(struct mtd_info *mtd, loff_t to,
1450 1445
1451 1446
1452/** 1447/**
1453 * onenand_do_write_oob - [Internal] OneNAND write out-of-band 1448 * onenand_write_oob_nolock - [Internal] OneNAND write out-of-band
1454 * @param mtd MTD device structure 1449 * @param mtd MTD device structure
1455 * @param to offset to write to 1450 * @param to offset to write to
1456 * @param len number of bytes to write 1451 * @param len number of bytes to write
@@ -1460,8 +1455,8 @@ static int onenand_write_ops(struct mtd_info *mtd, loff_t to,
1460 * 1455 *
1461 * OneNAND write out-of-band 1456 * OneNAND write out-of-band
1462 */ 1457 */
1463static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, 1458static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
1464 struct mtd_oob_ops *ops) 1459 struct mtd_oob_ops *ops)
1465{ 1460{
1466 struct onenand_chip *this = mtd->priv; 1461 struct onenand_chip *this = mtd->priv;
1467 int column, ret = 0, oobsize; 1462 int column, ret = 0, oobsize;
@@ -1473,7 +1468,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to,
1473 1468
1474 to += ops->ooboffs; 1469 to += ops->ooboffs;
1475 1470
1476 DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); 1471 DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
1477 1472
1478 /* Initialize retlen, in case of early exit */ 1473 /* Initialize retlen, in case of early exit */
1479 ops->oobretlen = 0; 1474 ops->oobretlen = 0;
@@ -1486,13 +1481,13 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to,
1486 column = to & (mtd->oobsize - 1); 1481 column = to & (mtd->oobsize - 1);
1487 1482
1488 if (unlikely(column >= oobsize)) { 1483 if (unlikely(column >= oobsize)) {
1489 printk(KERN_ERR "onenand_write_oob: Attempted to start write outside oob\n"); 1484 printk(KERN_ERR "onenand_write_oob_nolock: Attempted to start write outside oob\n");
1490 return -EINVAL; 1485 return -EINVAL;
1491 } 1486 }
1492 1487
1493 /* For compatibility with NAND: Do not allow write past end of page */ 1488 /* For compatibility with NAND: Do not allow write past end of page */
1494 if (unlikely(column + len > oobsize)) { 1489 if (unlikely(column + len > oobsize)) {
1495 printk(KERN_ERR "onenand_write_oob: " 1490 printk(KERN_ERR "onenand_write_oob_nolock: "
1496 "Attempt to write past end of page\n"); 1491 "Attempt to write past end of page\n");
1497 return -EINVAL; 1492 return -EINVAL;
1498 } 1493 }
@@ -1501,13 +1496,10 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to,
1501 if (unlikely(to >= mtd->size || 1496 if (unlikely(to >= mtd->size ||
1502 column + len > ((mtd->size >> this->page_shift) - 1497 column + len > ((mtd->size >> this->page_shift) -
1503 (to >> this->page_shift)) * oobsize)) { 1498 (to >> this->page_shift)) * oobsize)) {
1504 printk(KERN_ERR "onenand_write_oob: Attempted to write past end of device\n"); 1499 printk(KERN_ERR "onenand_write_oob_nolock: Attempted to write past end of device\n");
1505 return -EINVAL; 1500 return -EINVAL;
1506 } 1501 }
1507 1502
1508 /* Grab the lock and see if the device is available */
1509 onenand_get_device(mtd, FL_WRITING);
1510
1511 oobbuf = this->oob_buf; 1503 oobbuf = this->oob_buf;
1512 1504
1513 /* Loop until all data write */ 1505 /* Loop until all data write */
@@ -1537,13 +1529,13 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to,
1537 1529
1538 ret = this->wait(mtd, FL_WRITING); 1530 ret = this->wait(mtd, FL_WRITING);
1539 if (ret) { 1531 if (ret) {
1540 printk(KERN_ERR "onenand_write_oob: write failed %d\n", ret); 1532 printk(KERN_ERR "onenand_write_oob_nolock: write failed %d\n", ret);
1541 break; 1533 break;
1542 } 1534 }
1543 1535
1544 ret = onenand_verify_oob(mtd, oobbuf, to); 1536 ret = onenand_verify_oob(mtd, oobbuf, to);
1545 if (ret) { 1537 if (ret) {
1546 printk(KERN_ERR "onenand_write_oob: verify failed %d\n", ret); 1538 printk(KERN_ERR "onenand_write_oob_nolock: verify failed %d\n", ret);
1547 break; 1539 break;
1548 } 1540 }
1549 1541
@@ -1556,9 +1548,6 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to,
1556 column = 0; 1548 column = 0;
1557 } 1549 }
1558 1550
1559 /* Deselect and wake up anyone waiting on the device */
1560 onenand_release_device(mtd);
1561
1562 ops->oobretlen = written; 1551 ops->oobretlen = written;
1563 1552
1564 return ret; 1553 return ret;
@@ -1585,9 +1574,11 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
1585 }; 1574 };
1586 int ret; 1575 int ret;
1587 1576
1588 ret = onenand_write_ops(mtd, to, &ops); 1577 onenand_get_device(mtd, FL_WRITING);
1589 *retlen = ops.retlen; 1578 ret = onenand_write_ops_nolock(mtd, to, &ops);
1579 onenand_release_device(mtd);
1590 1580
1581 *retlen = ops.retlen;
1591 return ret; 1582 return ret;
1592} 1583}
1593 1584
@@ -1600,6 +1591,8 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
1600static int onenand_write_oob(struct mtd_info *mtd, loff_t to, 1591static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
1601 struct mtd_oob_ops *ops) 1592 struct mtd_oob_ops *ops)
1602{ 1593{
1594 int ret;
1595
1603 switch (ops->mode) { 1596 switch (ops->mode) {
1604 case MTD_OOB_PLACE: 1597 case MTD_OOB_PLACE:
1605 case MTD_OOB_AUTO: 1598 case MTD_OOB_AUTO:
@@ -1610,23 +1603,26 @@ static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
1610 return -EINVAL; 1603 return -EINVAL;
1611 } 1604 }
1612 1605
1606 onenand_get_device(mtd, FL_WRITING);
1613 if (ops->datbuf) 1607 if (ops->datbuf)
1614 return onenand_write_ops(mtd, to, ops); 1608 ret = onenand_write_ops_nolock(mtd, to, ops);
1609 else
1610 ret = onenand_write_oob_nolock(mtd, to, ops);
1611 onenand_release_device(mtd);
1615 1612
1616 return onenand_do_write_oob(mtd, to, ops); 1613 return ret;
1617} 1614}
1618 1615
1619/** 1616/**
1620 * onenand_block_checkbad - [GENERIC] Check if a block is marked bad 1617 * onenand_block_isbad_nolock - [GENERIC] Check if a block is marked bad
1621 * @param mtd MTD device structure 1618 * @param mtd MTD device structure
1622 * @param ofs offset from device start 1619 * @param ofs offset from device start
1623 * @param getchip 0, if the chip is already selected
1624 * @param allowbbt 1, if its allowed to access the bbt area 1620 * @param allowbbt 1, if its allowed to access the bbt area
1625 * 1621 *
1626 * Check, if the block is bad. Either by reading the bad block table or 1622 * Check, if the block is bad. Either by reading the bad block table or
1627 * calling of the scan function. 1623 * calling of the scan function.
1628 */ 1624 */
1629static int onenand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt) 1625static int onenand_block_isbad_nolock(struct mtd_info *mtd, loff_t ofs, int allowbbt)
1630{ 1626{
1631 struct onenand_chip *this = mtd->priv; 1627 struct onenand_chip *this = mtd->priv;
1632 struct bbm_info *bbm = this->bbm; 1628 struct bbm_info *bbm = this->bbm;
@@ -1687,7 +1683,7 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
1687 cond_resched(); 1683 cond_resched();
1688 1684
1689 /* Check if we have a bad block, we do not erase bad blocks */ 1685 /* Check if we have a bad block, we do not erase bad blocks */
1690 if (onenand_block_checkbad(mtd, addr, 0, 0)) { 1686 if (onenand_block_isbad_nolock(mtd, addr, 0)) {
1691 printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%08x\n", (unsigned int) addr); 1687 printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%08x\n", (unsigned int) addr);
1692 instr->state = MTD_ERASE_FAILED; 1688 instr->state = MTD_ERASE_FAILED;
1693 goto erase_exit; 1689 goto erase_exit;
@@ -1751,11 +1747,16 @@ static void onenand_sync(struct mtd_info *mtd)
1751 */ 1747 */
1752static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs) 1748static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
1753{ 1749{
1750 int ret;
1751
1754 /* Check for invalid offset */ 1752 /* Check for invalid offset */
1755 if (ofs > mtd->size) 1753 if (ofs > mtd->size)
1756 return -EINVAL; 1754 return -EINVAL;
1757 1755
1758 return onenand_block_checkbad(mtd, ofs, 1, 0); 1756 onenand_get_device(mtd, FL_READING);
1757 ret = onenand_block_isbad_nolock(mtd, ofs, 0);
1758 onenand_release_device(mtd);
1759 return ret;
1759} 1760}
1760 1761
1761/** 1762/**
@@ -1786,7 +1787,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
1786 1787
1787 /* We write two bytes, so we dont have to mess with 16 bit access */ 1788 /* We write two bytes, so we dont have to mess with 16 bit access */
1788 ofs += mtd->oobsize + (bbm->badblockpos & ~0x01); 1789 ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
1789 return onenand_do_write_oob(mtd, ofs, &ops); 1790 return onenand_write_oob_nolock(mtd, ofs, &ops);
1790} 1791}
1791 1792
1792/** 1793/**
@@ -1809,7 +1810,10 @@ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
1809 return ret; 1810 return ret;
1810 } 1811 }
1811 1812
1812 return this->block_markbad(mtd, ofs); 1813 onenand_get_device(mtd, FL_WRITING);
1814 ret = this->block_markbad(mtd, ofs);
1815 onenand_release_device(mtd);
1816 return ret;
1813} 1817}
1814 1818
1815/** 1819/**
@@ -2008,13 +2012,19 @@ static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len,
2008 size_t *retlen, u_char *buf) 2012 size_t *retlen, u_char *buf)
2009{ 2013{
2010 struct onenand_chip *this = mtd->priv; 2014 struct onenand_chip *this = mtd->priv;
2015 struct mtd_oob_ops ops = {
2016 .len = len,
2017 .ooblen = 0,
2018 .datbuf = buf,
2019 .oobbuf = NULL,
2020 };
2011 int ret; 2021 int ret;
2012 2022
2013 /* Enter OTP access mode */ 2023 /* Enter OTP access mode */
2014 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); 2024 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
2015 this->wait(mtd, FL_OTPING); 2025 this->wait(mtd, FL_OTPING);
2016 2026
2017 ret = mtd->read(mtd, from, len, retlen, buf); 2027 ret = onenand_read_ops_nolock(mtd, from, &ops);
2018 2028
2019 /* Exit OTP access mode */ 2029 /* Exit OTP access mode */
2020 this->command(mtd, ONENAND_CMD_RESET, 0, 0); 2030 this->command(mtd, ONENAND_CMD_RESET, 0, 0);
@@ -2026,19 +2036,20 @@ static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len,
2026/** 2036/**
2027 * do_otp_write - [DEFAULT] Write OTP block area 2037 * do_otp_write - [DEFAULT] Write OTP block area
2028 * @param mtd MTD device structure 2038 * @param mtd MTD device structure
2029 * @param from The offset to write 2039 * @param to The offset to write
2030 * @param len number of bytes to write 2040 * @param len number of bytes to write
2031 * @param retlen pointer to variable to store the number of write bytes 2041 * @param retlen pointer to variable to store the number of write bytes
2032 * @param buf the databuffer to put/get data 2042 * @param buf the databuffer to put/get data
2033 * 2043 *
2034 * Write OTP block area. 2044 * Write OTP block area.
2035 */ 2045 */
2036static int do_otp_write(struct mtd_info *mtd, loff_t from, size_t len, 2046static int do_otp_write(struct mtd_info *mtd, loff_t to, size_t len,
2037 size_t *retlen, u_char *buf) 2047 size_t *retlen, u_char *buf)
2038{ 2048{
2039 struct onenand_chip *this = mtd->priv; 2049 struct onenand_chip *this = mtd->priv;
2040 unsigned char *pbuf = buf; 2050 unsigned char *pbuf = buf;
2041 int ret; 2051 int ret;
2052 struct mtd_oob_ops ops;
2042 2053
2043 /* Force buffer page aligned */ 2054 /* Force buffer page aligned */
2044 if (len < mtd->writesize) { 2055 if (len < mtd->writesize) {
@@ -2052,7 +2063,12 @@ static int do_otp_write(struct mtd_info *mtd, loff_t from, size_t len,
2052 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); 2063 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
2053 this->wait(mtd, FL_OTPING); 2064 this->wait(mtd, FL_OTPING);
2054 2065
2055 ret = mtd->write(mtd, from, len, retlen, pbuf); 2066 ops.len = len;
2067 ops.ooblen = 0;
2068 ops.databuf = pbuf;
2069 ops.oobbuf = NULL;
2070 ret = onenand_write_ops_nolock(mtd, to, &ops);
2071 *retlen = ops.retlen;
2056 2072
2057 /* Exit OTP access mode */ 2073 /* Exit OTP access mode */
2058 this->command(mtd, ONENAND_CMD_RESET, 0, 0); 2074 this->command(mtd, ONENAND_CMD_RESET, 0, 0);
@@ -2087,7 +2103,7 @@ static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len,
2087 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); 2103 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
2088 this->wait(mtd, FL_OTPING); 2104 this->wait(mtd, FL_OTPING);
2089 2105
2090 ret = onenand_do_write_oob(mtd, from, &ops); 2106 ret = onenand_write_oob_nolock(mtd, from, &ops);
2091 2107
2092 *retlen = ops.oobretlen; 2108 *retlen = ops.oobretlen;
2093 2109
@@ -2136,13 +2152,16 @@ static int onenand_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
2136 if (((mtd->writesize * otp_pages) - (from + len)) < 0) 2152 if (((mtd->writesize * otp_pages) - (from + len)) < 0)
2137 return 0; 2153 return 0;
2138 2154
2155 onenand_get_device(mtd, FL_OTPING);
2139 while (len > 0 && otp_pages > 0) { 2156 while (len > 0 && otp_pages > 0) {
2140 if (!action) { /* OTP Info functions */ 2157 if (!action) { /* OTP Info functions */
2141 struct otp_info *otpinfo; 2158 struct otp_info *otpinfo;
2142 2159
2143 len -= sizeof(struct otp_info); 2160 len -= sizeof(struct otp_info);
2144 if (len <= 0) 2161 if (len <= 0) {
2145 return -ENOSPC; 2162 ret = -ENOSPC;
2163 break;
2164 }
2146 2165
2147 otpinfo = (struct otp_info *) buf; 2166 otpinfo = (struct otp_info *) buf;
2148 otpinfo->start = from; 2167 otpinfo->start = from;
@@ -2162,13 +2181,14 @@ static int onenand_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
2162 len -= size; 2181 len -= size;
2163 *retlen += size; 2182 *retlen += size;
2164 2183
2165 if (ret < 0) 2184 if (ret)
2166 return ret; 2185 break;
2167 } 2186 }
2168 otp_pages--; 2187 otp_pages--;
2169 } 2188 }
2189 onenand_release_device(mtd);
2170 2190
2171 return 0; 2191 return ret;
2172} 2192}
2173 2193
2174/** 2194/**
@@ -2364,7 +2384,7 @@ static void onenand_print_device_info(int device, int version)
2364 (16 << density), 2384 (16 << density),
2365 vcc ? "2.65/3.3" : "1.8", 2385 vcc ? "2.65/3.3" : "1.8",
2366 device); 2386 device);
2367 printk(KERN_DEBUG "OneNAND version = 0x%04x\n", version); 2387 printk(KERN_INFO "OneNAND version = 0x%04x\n", version);
2368} 2388}
2369 2389
2370static const struct onenand_manufacturers onenand_manuf_ids[] = { 2390static const struct onenand_manufacturers onenand_manuf_ids[] = {