diff options
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 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, * @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 9402653eb09b..4e74fe9af29e 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 */ |