diff options
Diffstat (limited to 'drivers/mtd/nftlcore.c')
-rw-r--r-- | drivers/mtd/nftlcore.c | 92 |
1 files changed, 76 insertions, 16 deletions
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index 359533b33d9b..f6ffe7949b26 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c | |||
@@ -134,6 +134,69 @@ static void nftl_remove_dev(struct mtd_blktrans_dev *dev) | |||
134 | kfree(nftl); | 134 | kfree(nftl); |
135 | } | 135 | } |
136 | 136 | ||
137 | /* | ||
138 | * Read oob data from flash | ||
139 | */ | ||
140 | int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, | ||
141 | size_t *retlen, uint8_t *buf) | ||
142 | { | ||
143 | struct mtd_oob_ops ops; | ||
144 | int res; | ||
145 | |||
146 | ops.mode = MTD_OOB_PLACE; | ||
147 | ops.ooboffs = offs & (mtd->writesize - 1); | ||
148 | ops.ooblen = len; | ||
149 | ops.oobbuf = buf; | ||
150 | ops.datbuf = NULL; | ||
151 | ops.len = len; | ||
152 | |||
153 | res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); | ||
154 | *retlen = ops.retlen; | ||
155 | return res; | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * Write oob data to flash | ||
160 | */ | ||
161 | int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, | ||
162 | size_t *retlen, uint8_t *buf) | ||
163 | { | ||
164 | struct mtd_oob_ops ops; | ||
165 | int res; | ||
166 | |||
167 | ops.mode = MTD_OOB_PLACE; | ||
168 | ops.ooboffs = offs & (mtd->writesize - 1); | ||
169 | ops.ooblen = len; | ||
170 | ops.oobbuf = buf; | ||
171 | ops.datbuf = NULL; | ||
172 | ops.len = len; | ||
173 | |||
174 | res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); | ||
175 | *retlen = ops.retlen; | ||
176 | return res; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * Write data and oob to flash | ||
181 | */ | ||
182 | static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len, | ||
183 | size_t *retlen, uint8_t *buf, uint8_t *oob) | ||
184 | { | ||
185 | struct mtd_oob_ops ops; | ||
186 | int res; | ||
187 | |||
188 | ops.mode = MTD_OOB_PLACE; | ||
189 | ops.ooboffs = offs; | ||
190 | ops.ooblen = mtd->oobsize; | ||
191 | ops.oobbuf = oob; | ||
192 | ops.datbuf = buf; | ||
193 | ops.len = len; | ||
194 | |||
195 | res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); | ||
196 | *retlen = ops.retlen; | ||
197 | return res; | ||
198 | } | ||
199 | |||
137 | #ifdef CONFIG_NFTL_RW | 200 | #ifdef CONFIG_NFTL_RW |
138 | 201 | ||
139 | /* Actual NFTL access routines */ | 202 | /* Actual NFTL access routines */ |
@@ -216,7 +279,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p | |||
216 | 279 | ||
217 | targetEUN = thisEUN; | 280 | targetEUN = thisEUN; |
218 | for (block = 0; block < nftl->EraseSize / 512; block ++) { | 281 | for (block = 0; block < nftl->EraseSize / 512; block ++) { |
219 | mtd->read_oob(mtd, (thisEUN * nftl->EraseSize) + | 282 | nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) + |
220 | (block * 512), 16 , &retlen, | 283 | (block * 512), 16 , &retlen, |
221 | (char *)&oob); | 284 | (char *)&oob); |
222 | if (block == 2) { | 285 | if (block == 2) { |
@@ -333,7 +396,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p | |||
333 | longer one */ | 396 | longer one */ |
334 | oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS); | 397 | oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS); |
335 | oob.u.c.unused = 0xffffffff; | 398 | oob.u.c.unused = 0xffffffff; |
336 | mtd->write_oob(mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, | 399 | nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, |
337 | 8, &retlen, (char *)&oob.u); | 400 | 8, &retlen, (char *)&oob.u); |
338 | } | 401 | } |
339 | 402 | ||
@@ -369,17 +432,15 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p | |||
369 | memset(&oob, 0xff, sizeof(struct nftl_oob)); | 432 | memset(&oob, 0xff, sizeof(struct nftl_oob)); |
370 | oob.b.Status = oob.b.Status1 = SECTOR_USED; | 433 | oob.b.Status = oob.b.Status1 = SECTOR_USED; |
371 | 434 | ||
372 | nand_write_raw(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + | 435 | nftl_write(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + |
373 | (block * 512), 512, &retlen, movebuf, | 436 | (block * 512), 512, &retlen, movebuf, (char *)&oob); |
374 | (char *)&oob); | ||
375 | |||
376 | } | 437 | } |
377 | 438 | ||
378 | /* add the header so that it is now a valid chain */ | 439 | /* add the header so that it is now a valid chain */ |
379 | oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); | 440 | oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); |
380 | oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; | 441 | oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; |
381 | 442 | ||
382 | mtd->write_oob(mtd, (nftl->EraseSize * targetEUN) + 8, | 443 | nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8, |
383 | 8, &retlen, (char *)&oob.u); | 444 | 8, &retlen, (char *)&oob.u); |
384 | 445 | ||
385 | /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */ | 446 | /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */ |
@@ -499,7 +560,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
499 | 560 | ||
500 | lastEUN = writeEUN; | 561 | lastEUN = writeEUN; |
501 | 562 | ||
502 | mtd->read_oob(mtd, | 563 | nftl_read_oob(mtd, |
503 | (writeEUN * nftl->EraseSize) + blockofs, | 564 | (writeEUN * nftl->EraseSize) + blockofs, |
504 | 8, &retlen, (char *)&bci); | 565 | 8, &retlen, (char *)&bci); |
505 | 566 | ||
@@ -588,12 +649,12 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
588 | nftl->ReplUnitTable[writeEUN] = BLOCK_NIL; | 649 | nftl->ReplUnitTable[writeEUN] = BLOCK_NIL; |
589 | 650 | ||
590 | /* ... and on the flash itself */ | 651 | /* ... and on the flash itself */ |
591 | mtd->read_oob(mtd, writeEUN * nftl->EraseSize + 8, 8, | 652 | nftl_read_oob(mtd, writeEUN * nftl->EraseSize + 8, 8, |
592 | &retlen, (char *)&oob.u); | 653 | &retlen, (char *)&oob.u); |
593 | 654 | ||
594 | oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); | 655 | oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); |
595 | 656 | ||
596 | mtd->write_oob(mtd, writeEUN * nftl->EraseSize + 8, 8, | 657 | nftl_write_oob(mtd, writeEUN * nftl->EraseSize + 8, 8, |
597 | &retlen, (char *)&oob.u); | 658 | &retlen, (char *)&oob.u); |
598 | 659 | ||
599 | /* we link the new block to the chain only after the | 660 | /* we link the new block to the chain only after the |
@@ -603,13 +664,13 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
603 | /* Both in our cache... */ | 664 | /* Both in our cache... */ |
604 | nftl->ReplUnitTable[lastEUN] = writeEUN; | 665 | nftl->ReplUnitTable[lastEUN] = writeEUN; |
605 | /* ... and on the flash itself */ | 666 | /* ... and on the flash itself */ |
606 | mtd->read_oob(mtd, (lastEUN * nftl->EraseSize) + 8, | 667 | nftl_read_oob(mtd, (lastEUN * nftl->EraseSize) + 8, |
607 | 8, &retlen, (char *)&oob.u); | 668 | 8, &retlen, (char *)&oob.u); |
608 | 669 | ||
609 | oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum | 670 | oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum |
610 | = cpu_to_le16(writeEUN); | 671 | = cpu_to_le16(writeEUN); |
611 | 672 | ||
612 | mtd->write_oob(mtd, (lastEUN * nftl->EraseSize) + 8, | 673 | nftl_write_oob(mtd, (lastEUN * nftl->EraseSize) + 8, |
613 | 8, &retlen, (char *)&oob.u); | 674 | 8, &retlen, (char *)&oob.u); |
614 | } | 675 | } |
615 | 676 | ||
@@ -643,9 +704,8 @@ static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, | |||
643 | memset(&oob, 0xff, sizeof(struct nftl_oob)); | 704 | memset(&oob, 0xff, sizeof(struct nftl_oob)); |
644 | oob.b.Status = oob.b.Status1 = SECTOR_USED; | 705 | oob.b.Status = oob.b.Status1 = SECTOR_USED; |
645 | 706 | ||
646 | nand_write_raw(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + | 707 | nftl_write(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs, |
647 | blockofs, 512, &retlen, (char *)buffer, | 708 | 512, &retlen, (char *)buffer, (char *)&oob); |
648 | (char *)&oob); | ||
649 | return 0; | 709 | return 0; |
650 | } | 710 | } |
651 | #endif /* CONFIG_NFTL_RW */ | 711 | #endif /* CONFIG_NFTL_RW */ |
@@ -667,7 +727,7 @@ static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block, | |||
667 | 727 | ||
668 | if (thisEUN != BLOCK_NIL) { | 728 | if (thisEUN != BLOCK_NIL) { |
669 | while (thisEUN < nftl->nb_blocks) { | 729 | while (thisEUN < nftl->nb_blocks) { |
670 | if (mtd->read_oob(mtd, (thisEUN * nftl->EraseSize) + | 730 | if (nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) + |
671 | blockofs, 8, &retlen, | 731 | blockofs, 8, &retlen, |
672 | (char *)&bci) < 0) | 732 | (char *)&bci) < 0) |
673 | status = SECTOR_IGNORE; | 733 | status = SECTOR_IGNORE; |