diff options
author | Maxim Levitsky <maximlevitsky@gmail.com> | 2010-02-22 13:39:36 -0500 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-02-26 12:47:47 -0500 |
commit | 782ce79a45b3b850b108896fcf7da26754061c8f (patch) | |
tree | 33048893319b835e1eeadbd89b9bf647d13cc81c /drivers/mtd/nand/nand_base.c | |
parent | 9aca334e854c319ccafea871006fda3814196e7b (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.c | 24 |
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 | */ |
2075 | static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, | 2075 | static 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 | ||