aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/inftlcore.c6
-rw-r--r--drivers/mtd/mtdchar.c12
-rw-r--r--drivers/mtd/mtdconcat.c39
-rw-r--r--drivers/mtd/mtdpart.c4
-rw-r--r--drivers/mtd/nand/nand_base.c51
-rw-r--r--drivers/mtd/nand/nand_bbt.c5
-rw-r--r--drivers/mtd/nftlcore.c6
-rw-r--r--drivers/mtd/ssfdc.c5
8 files changed, 74 insertions, 54 deletions
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index a1b2de60500..d2f54c037e0 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -163,10 +163,9 @@ int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
163 ops.ooblen = len; 163 ops.ooblen = len;
164 ops.oobbuf = buf; 164 ops.oobbuf = buf;
165 ops.datbuf = NULL; 165 ops.datbuf = NULL;
166 ops.len = len;
167 166
168 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 167 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
169 *retlen = ops.retlen; 168 *retlen = ops.oobretlen;
170 return res; 169 return res;
171} 170}
172 171
@@ -184,10 +183,9 @@ int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
184 ops.ooblen = len; 183 ops.ooblen = len;
185 ops.oobbuf = buf; 184 ops.oobbuf = buf;
186 ops.datbuf = NULL; 185 ops.datbuf = NULL;
187 ops.len = len;
188 186
189 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 187 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
190 *retlen = ops.retlen; 188 *retlen = ops.oobretlen;
191 return res; 189 return res;
192} 190}
193 191
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 866c8e0d57e..07618f51d96 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -499,13 +499,12 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
499 if (ret) 499 if (ret)
500 return ret; 500 return ret;
501 501
502 ops.len = buf.length;
503 ops.ooblen = buf.length; 502 ops.ooblen = buf.length;
504 ops.ooboffs = buf.start & (mtd->oobsize - 1); 503 ops.ooboffs = buf.start & (mtd->oobsize - 1);
505 ops.datbuf = NULL; 504 ops.datbuf = NULL;
506 ops.mode = MTD_OOB_PLACE; 505 ops.mode = MTD_OOB_PLACE;
507 506
508 if (ops.ooboffs && ops.len > (mtd->oobsize - ops.ooboffs)) 507 if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
509 return -EINVAL; 508 return -EINVAL;
510 509
511 ops.oobbuf = kmalloc(buf.length, GFP_KERNEL); 510 ops.oobbuf = kmalloc(buf.length, GFP_KERNEL);
@@ -520,7 +519,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
520 buf.start &= ~(mtd->oobsize - 1); 519 buf.start &= ~(mtd->oobsize - 1);
521 ret = mtd->write_oob(mtd, buf.start, &ops); 520 ret = mtd->write_oob(mtd, buf.start, &ops);
522 521
523 if (copy_to_user(argp + sizeof(uint32_t), &ops.retlen, 522 if (copy_to_user(argp + sizeof(uint32_t), &ops.oobretlen,
524 sizeof(uint32_t))) 523 sizeof(uint32_t)))
525 ret = -EFAULT; 524 ret = -EFAULT;
526 525
@@ -548,7 +547,6 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
548 if (ret) 547 if (ret)
549 return ret; 548 return ret;
550 549
551 ops.len = buf.length;
552 ops.ooblen = buf.length; 550 ops.ooblen = buf.length;
553 ops.ooboffs = buf.start & (mtd->oobsize - 1); 551 ops.ooboffs = buf.start & (mtd->oobsize - 1);
554 ops.datbuf = NULL; 552 ops.datbuf = NULL;
@@ -564,10 +562,10 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
564 buf.start &= ~(mtd->oobsize - 1); 562 buf.start &= ~(mtd->oobsize - 1);
565 ret = mtd->read_oob(mtd, buf.start, &ops); 563 ret = mtd->read_oob(mtd, buf.start, &ops);
566 564
567 if (put_user(ops.retlen, (uint32_t __user *)argp)) 565 if (put_user(ops.oobretlen, (uint32_t __user *)argp))
568 ret = -EFAULT; 566 ret = -EFAULT;
569 else if (ops.retlen && copy_to_user(buf.ptr, ops.oobbuf, 567 else if (ops.oobretlen && copy_to_user(buf.ptr, ops.oobbuf,
570 ops.retlen)) 568 ops.oobretlen))
571 ret = -EFAULT; 569 ret = -EFAULT;
572 570
573 kfree(ops.oobbuf); 571 kfree(ops.oobbuf);
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 1fea631b585..cf927a8803e 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -247,7 +247,7 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
247 struct mtd_oob_ops devops = *ops; 247 struct mtd_oob_ops devops = *ops;
248 int i, err, ret = 0; 248 int i, err, ret = 0;
249 249
250 ops->retlen = 0; 250 ops->retlen = ops->oobretlen = 0;
251 251
252 for (i = 0; i < concat->num_subdev; i++) { 252 for (i = 0; i < concat->num_subdev; i++) {
253 struct mtd_info *subdev = concat->subdev[i]; 253 struct mtd_info *subdev = concat->subdev[i];
@@ -263,6 +263,7 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
263 263
264 err = subdev->read_oob(subdev, from, &devops); 264 err = subdev->read_oob(subdev, from, &devops);
265 ops->retlen += devops.retlen; 265 ops->retlen += devops.retlen;
266 ops->oobretlen += devops.oobretlen;
266 267
267 /* Save information about bitflips! */ 268 /* Save information about bitflips! */
268 if (unlikely(err)) { 269 if (unlikely(err)) {
@@ -278,14 +279,18 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
278 return err; 279 return err;
279 } 280 }
280 281
281 devops.len = ops->len - ops->retlen; 282 if (devops.datbuf) {
282 if (!devops.len) 283 devops.len = ops->len - ops->retlen;
283 return ret; 284 if (!devops.len)
284 285 return ret;
285 if (devops.datbuf)
286 devops.datbuf += devops.retlen; 286 devops.datbuf += devops.retlen;
287 if (devops.oobbuf) 287 }
288 devops.oobbuf += devops.ooblen; 288 if (devops.oobbuf) {
289 devops.ooblen = ops->ooblen - ops->oobretlen;
290 if (!devops.ooblen)
291 return ret;
292 devops.oobbuf += ops->oobretlen;
293 }
289 294
290 from = 0; 295 from = 0;
291 } 296 }
@@ -321,14 +326,18 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
321 if (err) 326 if (err)
322 return err; 327 return err;
323 328
324 devops.len = ops->len - ops->retlen; 329 if (devops.datbuf) {
325 if (!devops.len) 330 devops.len = ops->len - ops->retlen;
326 return 0; 331 if (!devops.len)
327 332 return 0;
328 if (devops.datbuf)
329 devops.datbuf += devops.retlen; 333 devops.datbuf += devops.retlen;
330 if (devops.oobbuf) 334 }
331 devops.oobbuf += devops.ooblen; 335 if (devops.oobbuf) {
336 devops.ooblen = ops->ooblen - ops->oobretlen;
337 if (!devops.ooblen)
338 return 0;
339 devops.oobbuf += devops.oobretlen;
340 }
332 to = 0; 341 to = 0;
333 } 342 }
334 return -EINVAL; 343 return -EINVAL;
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 06a930372b7..a20f75fd8d6 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -94,7 +94,7 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
94 94
95 if (from >= mtd->size) 95 if (from >= mtd->size)
96 return -EINVAL; 96 return -EINVAL;
97 if (from + ops->len > mtd->size) 97 if (ops->datbuf && from + ops->len > mtd->size)
98 return -EINVAL; 98 return -EINVAL;
99 res = part->master->read_oob(part->master, from + part->offset, ops); 99 res = part->master->read_oob(part->master, from + part->offset, ops);
100 100
@@ -161,7 +161,7 @@ static int part_write_oob(struct mtd_info *mtd, loff_t to,
161 161
162 if (to >= mtd->size) 162 if (to >= mtd->size)
163 return -EINVAL; 163 return -EINVAL;
164 if (to + ops->len > mtd->size) 164 if (ops->datbuf && to + ops->len > mtd->size)
165 return -EINVAL; 165 return -EINVAL;
166 return part->master->write_oob(part->master, to + part->offset, ops); 166 return part->master->write_oob(part->master, to + part->offset, ops);
167} 167}
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 8df36e2c9a5..5dcb2e066ce 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,
897 * @chip: nand chip structure 897 * @chip: nand chip structure
898 * @oob: oob destination address 898 * @oob: oob destination address
899 * @ops: oob ops structure 899 * @ops: oob ops structure
900 * @len: size of oob to transfer
900 */ 901 */
901static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, 902static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
902 struct mtd_oob_ops *ops) 903 struct mtd_oob_ops *ops, size_t len)
903{ 904{
904 size_t len = ops->ooblen;
905
906 switch(ops->mode) { 905 switch(ops->mode) {
907 906
908 case MTD_OOB_PLACE: 907 case MTD_OOB_PLACE:
@@ -960,6 +959,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
960 int sndcmd = 1; 959 int sndcmd = 1;
961 int ret = 0; 960 int ret = 0;
962 uint32_t readlen = ops->len; 961 uint32_t readlen = ops->len;
962 uint32_t oobreadlen = ops->ooblen;
963 uint8_t *bufpoi, *oob, *buf; 963 uint8_t *bufpoi, *oob, *buf;
964 964
965 stats = mtd->ecc_stats; 965 stats = mtd->ecc_stats;
@@ -1006,10 +1006,17 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
1006 1006
1007 if (unlikely(oob)) { 1007 if (unlikely(oob)) {
1008 /* Raw mode does data:oob:data:oob */ 1008 /* Raw mode does data:oob:data:oob */
1009 if (ops->mode != MTD_OOB_RAW) 1009 if (ops->mode != MTD_OOB_RAW) {
1010 oob = nand_transfer_oob(chip, oob, ops); 1010 int toread = min(oobreadlen,
1011 else 1011 chip->ecc.layout->oobavail);
1012 buf = nand_transfer_oob(chip, buf, ops); 1012 if (toread) {
1013 oob = nand_transfer_oob(chip,
1014 oob, ops, toread);
1015 oobreadlen -= toread;
1016 }
1017 } else
1018 buf = nand_transfer_oob(chip,
1019 buf, ops, mtd->oobsize);
1013 } 1020 }
1014 1021
1015 if (!(chip->options & NAND_NO_READRDY)) { 1022 if (!(chip->options & NAND_NO_READRDY)) {
@@ -1056,6 +1063,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
1056 } 1063 }
1057 1064
1058 ops->retlen = ops->len - (size_t) readlen; 1065 ops->retlen = ops->len - (size_t) readlen;
1066 if (oob)
1067 ops->oobretlen = ops->ooblen - oobreadlen;
1059 1068
1060 if (ret) 1069 if (ret)
1061 return ret; 1070 return ret;
@@ -1256,12 +1265,18 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1256 int page, realpage, chipnr, sndcmd = 1; 1265 int page, realpage, chipnr, sndcmd = 1;
1257 struct nand_chip *chip = mtd->priv; 1266 struct nand_chip *chip = mtd->priv;
1258 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; 1267 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1259 int readlen = ops->len; 1268 int readlen = ops->ooblen;
1269 int len;
1260 uint8_t *buf = ops->oobbuf; 1270 uint8_t *buf = ops->oobbuf;
1261 1271
1262 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n", 1272 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n",
1263 (unsigned long long)from, readlen); 1273 (unsigned long long)from, readlen);
1264 1274
1275 if (ops->mode == MTD_OOB_RAW)
1276 len = mtd->oobsize;
1277 else
1278 len = chip->ecc.layout->oobavail;
1279
1265 chipnr = (int)(from >> chip->chip_shift); 1280 chipnr = (int)(from >> chip->chip_shift);
1266 chip->select_chip(mtd, chipnr); 1281 chip->select_chip(mtd, chipnr);
1267 1282
@@ -1271,7 +1286,9 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1271 1286
1272 while(1) { 1287 while(1) {
1273 sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); 1288 sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
1274 buf = nand_transfer_oob(chip, buf, ops); 1289
1290 len = min(len, readlen);
1291 buf = nand_transfer_oob(chip, buf, ops, len);
1275 1292
1276 if (!(chip->options & NAND_NO_READRDY)) { 1293 if (!(chip->options & NAND_NO_READRDY)) {
1277 /* 1294 /*
@@ -1286,7 +1303,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1286 nand_wait_ready(mtd); 1303 nand_wait_ready(mtd);
1287 } 1304 }
1288 1305
1289 readlen -= ops->ooblen; 1306 readlen -= len;
1290 if (!readlen) 1307 if (!readlen)
1291 break; 1308 break;
1292 1309
@@ -1308,7 +1325,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1308 sndcmd = 1; 1325 sndcmd = 1;
1309 } 1326 }
1310 1327
1311 ops->retlen = ops->len; 1328 ops->oobretlen = ops->ooblen;
1312 return 0; 1329 return 0;
1313} 1330}
1314 1331
@@ -1329,7 +1346,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
1329 ops->retlen = 0; 1346 ops->retlen = 0;
1330 1347
1331 /* Do not allow reads past end of device */ 1348 /* Do not allow reads past end of device */
1332 if ((from + ops->len) > mtd->size) { 1349 if (ops->datbuf && (from + ops->len) > mtd->size) {
1333 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " 1350 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1334 "Attempt read beyond end of device\n"); 1351 "Attempt read beyond end of device\n");
1335 return -EINVAL; 1352 return -EINVAL;
@@ -1654,6 +1671,8 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
1654 } 1671 }
1655 1672
1656 ops->retlen = ops->len - writelen; 1673 ops->retlen = ops->len - writelen;
1674 if (unlikely(oob))
1675 ops->oobretlen = ops->ooblen;
1657 return ret; 1676 return ret;
1658} 1677}
1659 1678
@@ -1709,10 +1728,10 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
1709 struct nand_chip *chip = mtd->priv; 1728 struct nand_chip *chip = mtd->priv;
1710 1729
1711 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", 1730 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
1712 (unsigned int)to, (int)ops->len); 1731 (unsigned int)to, (int)ops->ooblen);
1713 1732
1714 /* Do not allow write past end of page */ 1733 /* Do not allow write past end of page */
1715 if ((ops->ooboffs + ops->len) > mtd->oobsize) { 1734 if ((ops->ooboffs + ops->ooblen) > mtd->oobsize) {
1716 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " 1735 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1717 "Attempt to write past end of page\n"); 1736 "Attempt to write past end of page\n");
1718 return -EINVAL; 1737 return -EINVAL;
@@ -1748,7 +1767,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
1748 if (status) 1767 if (status)
1749 return status; 1768 return status;
1750 1769
1751 ops->retlen = ops->len; 1770 ops->oobretlen = ops->ooblen;
1752 1771
1753 return 0; 1772 return 0;
1754} 1773}
@@ -1768,7 +1787,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
1768 ops->retlen = 0; 1787 ops->retlen = 0;
1769 1788
1770 /* Do not allow writes past end of device */ 1789 /* Do not allow writes past end of device */
1771 if ((to + ops->len) > mtd->size) { 1790 if (ops->datbuf && (to + ops->len) > mtd->size) {
1772 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " 1791 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1773 "Attempt read beyond end of device\n"); 1792 "Attempt read beyond end of device\n");
1774 return -EINVAL; 1793 return -EINVAL;
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 9402653eb09..4e74fe9af29 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,
333 struct mtd_oob_ops ops; 333 struct mtd_oob_ops ops;
334 int j, ret; 334 int j, ret;
335 335
336 ops.len = mtd->oobsize;
337 ops.ooblen = mtd->oobsize; 336 ops.ooblen = mtd->oobsize;
338 ops.oobbuf = buf; 337 ops.oobbuf = buf;
339 ops.ooboffs = 0; 338 ops.ooboffs = 0;
@@ -676,10 +675,10 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
676 "bad block table\n"); 675 "bad block table\n");
677 } 676 }
678 /* Read oob data */ 677 /* Read oob data */
679 ops.len = (len >> this->page_shift) * mtd->oobsize; 678 ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
680 ops.oobbuf = &buf[len]; 679 ops.oobbuf = &buf[len];
681 res = mtd->read_oob(mtd, to + mtd->writesize, &ops); 680 res = mtd->read_oob(mtd, to + mtd->writesize, &ops);
682 if (res < 0 || ops.retlen != ops.len) 681 if (res < 0 || ops.oobretlen != ops.ooblen)
683 goto outerr; 682 goto outerr;
684 683
685 /* Calc the byte offset in the buffer */ 684 /* Calc the byte offset in the buffer */
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index d974adab349..f4d38546068 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -147,10 +147,9 @@ int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
147 ops.ooblen = len; 147 ops.ooblen = len;
148 ops.oobbuf = buf; 148 ops.oobbuf = buf;
149 ops.datbuf = NULL; 149 ops.datbuf = NULL;
150 ops.len = len;
151 150
152 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 151 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
153 *retlen = ops.retlen; 152 *retlen = ops.oobretlen;
154 return res; 153 return res;
155} 154}
156 155
@@ -168,10 +167,9 @@ int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
168 ops.ooblen = len; 167 ops.ooblen = len;
169 ops.oobbuf = buf; 168 ops.oobbuf = buf;
170 ops.datbuf = NULL; 169 ops.datbuf = NULL;
171 ops.len = len;
172 170
173 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 171 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
174 *retlen = ops.retlen; 172 *retlen = ops.oobretlen;
175 return res; 173 return res;
176} 174}
177 175
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c
index 79d3bb659bf..e834cc16c9f 100644
--- a/drivers/mtd/ssfdc.c
+++ b/drivers/mtd/ssfdc.c
@@ -172,13 +172,12 @@ static int read_raw_oob(struct mtd_info *mtd, loff_t offs, uint8_t *buf)
172 172
173 ops.mode = MTD_OOB_RAW; 173 ops.mode = MTD_OOB_RAW;
174 ops.ooboffs = 0; 174 ops.ooboffs = 0;
175 ops.ooblen = mtd->oobsize; 175 ops.ooblen = OOB_SIZE;
176 ops.len = OOB_SIZE;
177 ops.oobbuf = buf; 176 ops.oobbuf = buf;
178 ops.datbuf = NULL; 177 ops.datbuf = NULL;
179 178
180 ret = mtd->read_oob(mtd, offs, &ops); 179 ret = mtd->read_oob(mtd, offs, &ops);
181 if (ret < 0 || ops.retlen != OOB_SIZE) 180 if (ret < 0 || ops.oobretlen != OOB_SIZE)
182 return -1; 181 return -1;
183 182
184 return 0; 183 return 0;