Commit 782ce79a authored by Maxim Levitsky's avatar Maxim Levitsky Committed by David Woodhouse

mtd: nand: cleanup the nand_do_write_ops

nand_do_write_ops was broken in regard to writing several pages, each 
with its own oob.

Although nand_do_write_ops intends to allow such mode, it fails do do so
Probably this was never tested.

Also add missing checks for attempts to write at illegal offsets.
Signed-off-by: default avatarMaxim Levitsky <maximlevitsky@gmail.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 9aca334e
...@@ -2072,11 +2072,9 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -2072,11 +2072,9 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
* @oob: oob data buffer * @oob: oob data buffer
* @ops: oob ops structure * @ops: oob ops structure
*/ */
static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
struct mtd_oob_ops *ops) struct mtd_oob_ops *ops)
{ {
size_t len = ops->ooblen;
switch(ops->mode) { switch(ops->mode) {
case MTD_OOB_PLACE: case MTD_OOB_PLACE:
...@@ -2131,6 +2129,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, ...@@ -2131,6 +2129,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
int chipnr, realpage, page, blockmask, column; int chipnr, realpage, page, blockmask, column;
struct nand_chip *chip = mtd->priv; struct nand_chip *chip = mtd->priv;
uint32_t writelen = ops->len; uint32_t writelen = ops->len;
uint32_t oobwritelen = ops->ooblen;
uint32_t oobmaxlen = ops->mode == MTD_OOB_AUTO ?
mtd->oobavail : mtd->oobsize;
uint8_t *oob = ops->oobbuf; uint8_t *oob = ops->oobbuf;
uint8_t *buf = ops->datbuf; uint8_t *buf = ops->datbuf;
int ret, subpage; int ret, subpage;
...@@ -2172,6 +2175,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, ...@@ -2172,6 +2175,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
if (likely(!oob)) if (likely(!oob))
memset(chip->oob_poi, 0xff, mtd->oobsize); memset(chip->oob_poi, 0xff, mtd->oobsize);
/* Don't allow multipage oob writes with offset */
if (ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen))
return -EINVAL;
while(1) { while(1) {
int bytes = mtd->writesize; int bytes = mtd->writesize;
int cached = writelen > bytes && page != blockmask; int cached = writelen > bytes && page != blockmask;
...@@ -2187,8 +2194,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, ...@@ -2187,8 +2194,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
wbuf = chip->buffers->databuf; wbuf = chip->buffers->databuf;
} }
if (unlikely(oob)) if (unlikely(oob)) {
oob = nand_fill_oob(chip, oob, ops); size_t len = min(oobwritelen, oobmaxlen);
oob = nand_fill_oob(chip, oob, len, ops);
oobwritelen -= len;
}
ret = chip->write_page(mtd, chip, wbuf, page, cached, ret = chip->write_page(mtd, chip, wbuf, page, cached,
(ops->mode == MTD_OOB_RAW)); (ops->mode == MTD_OOB_RAW));
...@@ -2362,7 +2372,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, ...@@ -2362,7 +2372,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
chip->pagebuf = -1; chip->pagebuf = -1;
memset(chip->oob_poi, 0xff, mtd->oobsize); memset(chip->oob_poi, 0xff, mtd->oobsize);
nand_fill_oob(chip, ops->oobbuf, ops); nand_fill_oob(chip, ops->oobbuf, ops->ooblen, ops);
status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
memset(chip->oob_poi, 0xff, mtd->oobsize); memset(chip->oob_poi, 0xff, mtd->oobsize);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment