diff options
author | Vitaly Wool <vwool@ru.mvista.com> | 2006-11-03 15:20:38 (GMT) |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-11-28 22:39:03 (GMT) |
commit | 7014568bad55c20b7ee4f439d78c9e875912d51f (patch) | |
tree | 1b558ef8d77d31925cc396ed69d8f785615cf09f /drivers/mtd/nand | |
parent | 191876729901d0c8dab8a331f9a1e4b73a56457b (diff) | |
download | linux-7014568bad55c20b7ee4f439d78c9e875912d51f.tar.xz |
[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')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 51 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_bbt.c | 5 |
2 files changed, 37 insertions, 19 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 8df36e2..5dcb2e0 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, * @chip: nand chip structure * @oob: oob destination address * @ops: oob ops structure + * @len: size of oob to transfer */ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, - struct mtd_oob_ops *ops) + struct mtd_oob_ops *ops, size_t len) { - size_t len = ops->ooblen; - switch(ops->mode) { case MTD_OOB_PLACE: @@ -960,6 +959,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, int sndcmd = 1; int ret = 0; uint32_t readlen = ops->len; + uint32_t oobreadlen = ops->ooblen; uint8_t *bufpoi, *oob, *buf; stats = mtd->ecc_stats; @@ -1006,10 +1006,17 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, if (unlikely(oob)) { /* Raw mode does data:oob:data:oob */ - if (ops->mode != MTD_OOB_RAW) - oob = nand_transfer_oob(chip, oob, ops); - else - buf = nand_transfer_oob(chip, buf, ops); + if (ops->mode != MTD_OOB_RAW) { + int toread = min(oobreadlen, + chip->ecc.layout->oobavail); + if (toread) { + oob = nand_transfer_oob(chip, + oob, ops, toread); + oobreadlen -= toread; + } + } else + buf = nand_transfer_oob(chip, + buf, ops, mtd->oobsize); } if (!(chip->options & NAND_NO_READRDY)) { @@ -1056,6 +1063,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, } ops->retlen = ops->len - (size_t) readlen; + if (oob) + ops->oobretlen = ops->ooblen - oobreadlen; if (ret) return ret; @@ -1256,12 +1265,18 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, int page, realpage, chipnr, sndcmd = 1; struct nand_chip *chip = mtd->priv; int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; - int readlen = ops->len; + int readlen = ops->ooblen; + int len; uint8_t *buf = ops->oobbuf; DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n", (unsigned long long)from, readlen); + if (ops->mode == MTD_OOB_RAW) + len = mtd->oobsize; + else + len = chip->ecc.layout->oobavail; + chipnr = (int)(from >> chip->chip_shift); chip->select_chip(mtd, chipnr); @@ -1271,7 +1286,9 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, while(1) { sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); - buf = nand_transfer_oob(chip, buf, ops); + + len = min(len, readlen); + buf = nand_transfer_oob(chip, buf, ops, len); if (!(chip->options & NAND_NO_READRDY)) { /* @@ -1286,7 +1303,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, nand_wait_ready(mtd); } - readlen -= ops->ooblen; + readlen -= len; if (!readlen) break; @@ -1308,7 +1325,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, sndcmd = 1; } - ops->retlen = ops->len; + ops->oobretlen = ops->ooblen; return 0; } @@ -1329,7 +1346,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, ops->retlen = 0; /* Do not allow reads past end of device */ - if ((from + ops->len) > mtd->size) { + if (ops->datbuf && (from + ops->len) > mtd->size) { DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " "Attempt read beyond end of device\n"); return -EINVAL; @@ -1654,6 +1671,8 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, } ops->retlen = ops->len - writelen; + if (unlikely(oob)) + ops->oobretlen = ops->ooblen; return ret; } @@ -1709,10 +1728,10 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, struct nand_chip *chip = mtd->priv; DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", - (unsigned int)to, (int)ops->len); + (unsigned int)to, (int)ops->ooblen); /* Do not allow write past end of page */ - if ((ops->ooboffs + ops->len) > mtd->oobsize) { + if ((ops->ooboffs + ops->ooblen) > mtd->oobsize) { DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Attempt to write past end of page\n"); return -EINVAL; @@ -1748,7 +1767,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, if (status) return status; - ops->retlen = ops->len; + ops->oobretlen = ops->ooblen; return 0; } @@ -1768,7 +1787,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, ops->retlen = 0; /* Do not allow writes past end of device */ - if ((to + ops->len) > mtd->size) { + if (ops->datbuf && (to + ops->len) > mtd->size) { DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " "Attempt read beyond end of device\n"); return -EINVAL; diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 9402653..4e74fe9 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -333,7 +333,6 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, struct mtd_oob_ops ops; int j, ret; - ops.len = mtd->oobsize; ops.ooblen = mtd->oobsize; ops.oobbuf = buf; ops.ooboffs = 0; @@ -676,10 +675,10 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, "bad block table\n"); } /* Read oob data */ - ops.len = (len >> this->page_shift) * mtd->oobsize; + ops.ooblen = (len >> this->page_shift) * mtd->oobsize; ops.oobbuf = &buf[len]; res = mtd->read_oob(mtd, to + mtd->writesize, &ops); - if (res < 0 || ops.retlen != ops.len) + if (res < 0 || ops.oobretlen != ops.ooblen) goto outerr; /* Calc the byte offset in the buffer */ |