aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/nand_base.c
diff options
context:
space:
mode:
authorVitaly Wool <vwool@ru.mvista.com>2006-11-03 10:20:38 -0500
committerDavid Woodhouse <dwmw2@infradead.org>2006-11-28 17:39:03 -0500
commit7014568bad55c20b7ee4f439d78c9e875912d51f (patch)
tree1b558ef8d77d31925cc396ed69d8f785615cf09f /drivers/mtd/nand/nand_base.c
parent191876729901d0c8dab8a331f9a1e4b73a56457b (diff)
[MTD] [NAND] remove len/ooblen confusion.
As was discussed between Ricard Wanderlöf, David Woodhouse, Artem Bityutskiy and me, the current API for reading/writing OOB is confusing. The thing that introduces confusion is the need to specify ops.len together with ops.ooblen for reads/writes that concern only OOB not data area. So, ops.len is overloaded: when ops.datbuf != NULL it serves to specify the length of the data read, and when ops.datbuf == NULL, it serves to specify the full OOB read length. The patch inlined below is the slightly updated version of the previous patch serving the same purpose, but with the new Artem's comments taken into account. Artem, BTW, thanks a lot for your valuable input! Signed-off-by: Vitaly Wool <vwool@ru.mvista.com> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
-rw-r--r--drivers/mtd/nand/nand_base.c51
1 files changed, 35 insertions, 16 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 8df36e2c9a53..5dcb2e066ce7 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -897,12 +897,11 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
897 * @chip: nand chip structure 897 * @chip: nand chip structure
898 * @oob: oob destination address 898 * @oob: oob destination address
899 * @ops: oob ops structure 899 * @ops: oob ops structure
900 * @len: size of oob to transfer
900 */ 901 */
901static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, 902static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
902 struct mtd_oob_ops *ops) 903 struct mtd_oob_ops *ops, size_t len)
903{ 904{
904 size_t len = ops->ooblen;
905
906 switch(ops->mode) { 905 switch(ops->mode) {
907 906
908 case MTD_OOB_PLACE: 907 case MTD_OOB_PLACE:
@@ -960,6 +959,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
960 int sndcmd = 1; 959 int sndcmd = 1;
961 int ret = 0; 960 int ret = 0;
962 uint32_t readlen = ops->len; 961 uint32_t readlen = ops->len;
962 uint32_t oobreadlen = ops->ooblen;
963 uint8_t *bufpoi, *oob, *buf; 963 uint8_t *bufpoi, *oob, *buf;
964 964
965 stats = mtd->ecc_stats; 965 stats = mtd->ecc_stats;
@@ -1006,10 +1006,17 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
1006 1006
1007 if (unlikely(oob)) { 1007 if (unlikely(oob)) {
1008 /* Raw mode does data:oob:data:oob */ 1008 /* Raw mode does data:oob:data:oob */
1009 if (ops->mode != MTD_OOB_RAW) 1009 if (ops->mode != MTD_OOB_RAW) {
1010 oob = nand_transfer_oob(chip, oob, ops); 1010 int toread = min(oobreadlen,
1011 else 1011 chip->ecc.layout->oobavail);
1012 buf = nand_transfer_oob(chip, buf, ops); 1012 if (toread) {
1013 oob = nand_transfer_oob(chip,
1014 oob, ops, toread);
1015 oobreadlen -= toread;
1016 }
1017 } else
1018 buf = nand_transfer_oob(chip,
1019 buf, ops, mtd->oobsize);
1013 } 1020 }
1014 1021
1015 if (!(chip->options & NAND_NO_READRDY)) { 1022 if (!(chip->options & NAND_NO_READRDY)) {
@@ -1056,6 +1063,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
1056 } 1063 }
1057 1064
1058 ops->retlen = ops->len - (size_t) readlen; 1065 ops->retlen = ops->len - (size_t) readlen;
1066 if (oob)
1067 ops->oobretlen = ops->ooblen - oobreadlen;
1059 1068
1060 if (ret) 1069 if (ret)
1061 return ret; 1070 return ret;
@@ -1256,12 +1265,18 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1256 int page, realpage, chipnr, sndcmd = 1; 1265 int page, realpage, chipnr, sndcmd = 1;
1257 struct nand_chip *chip = mtd->priv; 1266 struct nand_chip *chip = mtd->priv;
1258 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; 1267 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1259 int readlen = ops->len; 1268 int readlen = ops->ooblen;
1269 int len;
1260 uint8_t *buf = ops->oobbuf; 1270 uint8_t *buf = ops->oobbuf;
1261 1271
1262 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n", 1272 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n",
1263 (unsigned long long)from, readlen); 1273 (unsigned long long)from, readlen);
1264 1274
1275 if (ops->mode == MTD_OOB_RAW)
1276 len = mtd->oobsize;
1277 else
1278 len = chip->ecc.layout->oobavail;
1279
1265 chipnr = (int)(from >> chip->chip_shift); 1280 chipnr = (int)(from >> chip->chip_shift);
1266 chip->select_chip(mtd, chipnr); 1281 chip->select_chip(mtd, chipnr);
1267 1282
@@ -1271,7 +1286,9 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1271 1286
1272 while(1) { 1287 while(1) {
1273 sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); 1288 sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
1274 buf = nand_transfer_oob(chip, buf, ops); 1289
1290 len = min(len, readlen);
1291 buf = nand_transfer_oob(chip, buf, ops, len);
1275 1292
1276 if (!(chip->options & NAND_NO_READRDY)) { 1293 if (!(chip->options & NAND_NO_READRDY)) {
1277 /* 1294 /*
@@ -1286,7 +1303,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1286 nand_wait_ready(mtd); 1303 nand_wait_ready(mtd);
1287 } 1304 }
1288 1305
1289 readlen -= ops->ooblen; 1306 readlen -= len;
1290 if (!readlen) 1307 if (!readlen)
1291 break; 1308 break;
1292 1309
@@ -1308,7 +1325,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1308 sndcmd = 1; 1325 sndcmd = 1;
1309 } 1326 }
1310 1327
1311 ops->retlen = ops->len; 1328 ops->oobretlen = ops->ooblen;
1312 return 0; 1329 return 0;
1313} 1330}
1314 1331
@@ -1329,7 +1346,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
1329 ops->retlen = 0; 1346 ops->retlen = 0;
1330 1347
1331 /* Do not allow reads past end of device */ 1348 /* Do not allow reads past end of device */
1332 if ((from + ops->len) > mtd->size) { 1349 if (ops->datbuf && (from + ops->len) > mtd->size) {
1333 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " 1350 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1334 "Attempt read beyond end of device\n"); 1351 "Attempt read beyond end of device\n");
1335 return -EINVAL; 1352 return -EINVAL;
@@ -1654,6 +1671,8 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
1654 } 1671 }
1655 1672
1656 ops->retlen = ops->len - writelen; 1673 ops->retlen = ops->len - writelen;
1674 if (unlikely(oob))
1675 ops->oobretlen = ops->ooblen;
1657 return ret; 1676 return ret;
1658} 1677}
1659 1678
@@ -1709,10 +1728,10 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
1709 struct nand_chip *chip = mtd->priv; 1728 struct nand_chip *chip = mtd->priv;
1710 1729
1711 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", 1730 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
1712 (unsigned int)to, (int)ops->len); 1731 (unsigned int)to, (int)ops->ooblen);
1713 1732
1714 /* Do not allow write past end of page */ 1733 /* Do not allow write past end of page */
1715 if ((ops->ooboffs + ops->len) > mtd->oobsize) { 1734 if ((ops->ooboffs + ops->ooblen) > mtd->oobsize) {
1716 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " 1735 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1717 "Attempt to write past end of page\n"); 1736 "Attempt to write past end of page\n");
1718 return -EINVAL; 1737 return -EINVAL;
@@ -1748,7 +1767,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
1748 if (status) 1767 if (status)
1749 return status; 1768 return status;
1750 1769
1751 ops->retlen = ops->len; 1770 ops->oobretlen = ops->ooblen;
1752 1771
1753 return 0; 1772 return 0;
1754} 1773}
@@ -1768,7 +1787,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
1768 ops->retlen = 0; 1787 ops->retlen = 0;
1769 1788
1770 /* Do not allow writes past end of device */ 1789 /* Do not allow writes past end of device */
1771 if ((to + ops->len) > mtd->size) { 1790 if (ops->datbuf && (to + ops->len) > mtd->size) {
1772 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " 1791 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1773 "Attempt read beyond end of device\n"); 1792 "Attempt read beyond end of device\n");
1774 return -EINVAL; 1793 return -EINVAL;