aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/nand_base.c
diff options
context:
space:
mode:
authorMaxim Levitsky <maximlevitsky@gmail.com>2010-02-22 13:39:36 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2010-02-26 12:47:47 -0500
commit782ce79a45b3b850b108896fcf7da26754061c8f (patch)
tree33048893319b835e1eeadbd89b9bf647d13cc81c /drivers/mtd/nand/nand_base.c
parent9aca334e854c319ccafea871006fda3814196e7b (diff)
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: Maxim Levitsky <maximlevitsky@gmail.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
-rw-r--r--drivers/mtd/nand/nand_base.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index cada4cffacf8..138674183c1c 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2072,11 +2072,9 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
2072 * @oob: oob data buffer 2072 * @oob: oob data buffer
2073 * @ops: oob ops structure 2073 * @ops: oob ops structure
2074 */ 2074 */
2075static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, 2075static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
2076 struct mtd_oob_ops *ops) 2076 struct mtd_oob_ops *ops)
2077{ 2077{
2078 size_t len = ops->ooblen;
2079
2080 switch(ops->mode) { 2078 switch(ops->mode) {
2081 2079
2082 case MTD_OOB_PLACE: 2080 case MTD_OOB_PLACE:
@@ -2131,6 +2129,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
2131 int chipnr, realpage, page, blockmask, column; 2129 int chipnr, realpage, page, blockmask, column;
2132 struct nand_chip *chip = mtd->priv; 2130 struct nand_chip *chip = mtd->priv;
2133 uint32_t writelen = ops->len; 2131 uint32_t writelen = ops->len;
2132
2133 uint32_t oobwritelen = ops->ooblen;
2134 uint32_t oobmaxlen = ops->mode == MTD_OOB_AUTO ?
2135 mtd->oobavail : mtd->oobsize;
2136
2134 uint8_t *oob = ops->oobbuf; 2137 uint8_t *oob = ops->oobbuf;
2135 uint8_t *buf = ops->datbuf; 2138 uint8_t *buf = ops->datbuf;
2136 int ret, subpage; 2139 int ret, subpage;
@@ -2172,6 +2175,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
2172 if (likely(!oob)) 2175 if (likely(!oob))
2173 memset(chip->oob_poi, 0xff, mtd->oobsize); 2176 memset(chip->oob_poi, 0xff, mtd->oobsize);
2174 2177
2178 /* Don't allow multipage oob writes with offset */
2179 if (ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen))
2180 return -EINVAL;
2181
2175 while(1) { 2182 while(1) {
2176 int bytes = mtd->writesize; 2183 int bytes = mtd->writesize;
2177 int cached = writelen > bytes && page != blockmask; 2184 int cached = writelen > bytes && page != blockmask;
@@ -2187,8 +2194,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
2187 wbuf = chip->buffers->databuf; 2194 wbuf = chip->buffers->databuf;
2188 } 2195 }
2189 2196
2190 if (unlikely(oob)) 2197 if (unlikely(oob)) {
2191 oob = nand_fill_oob(chip, oob, ops); 2198 size_t len = min(oobwritelen, oobmaxlen);
2199 oob = nand_fill_oob(chip, oob, len, ops);
2200 oobwritelen -= len;
2201 }
2192 2202
2193 ret = chip->write_page(mtd, chip, wbuf, page, cached, 2203 ret = chip->write_page(mtd, chip, wbuf, page, cached,
2194 (ops->mode == MTD_OOB_RAW)); 2204 (ops->mode == MTD_OOB_RAW));
@@ -2362,7 +2372,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
2362 chip->pagebuf = -1; 2372 chip->pagebuf = -1;
2363 2373
2364 memset(chip->oob_poi, 0xff, mtd->oobsize); 2374 memset(chip->oob_poi, 0xff, mtd->oobsize);
2365 nand_fill_oob(chip, ops->oobbuf, ops); 2375 nand_fill_oob(chip, ops->oobbuf, ops->ooblen, ops);
2366 status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); 2376 status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
2367 memset(chip->oob_poi, 0xff, mtd->oobsize); 2377 memset(chip->oob_poi, 0xff, mtd->oobsize);
2368 2378