diff options
Diffstat (limited to 'fs/jffs2/wbuf.c')
-rw-r--r-- | fs/jffs2/wbuf.c | 164 |
1 files changed, 108 insertions, 56 deletions
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index c8128069ecf0..996d922e503e 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * | 9 | * |
10 | * For licensing information, see the file 'LICENCE' in this directory. | 10 | * For licensing information, see the file 'LICENCE' in this directory. |
11 | * | 11 | * |
12 | * $Id: wbuf.c,v 1.82 2004/11/20 22:08:31 dwmw2 Exp $ | 12 | * $Id: wbuf.c,v 1.92 2005/04/05 12:51:54 dedekind Exp $ |
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
@@ -83,7 +83,7 @@ static void jffs2_wbuf_dirties_inode(struct jffs2_sb_info *c, uint32_t ino) | |||
83 | struct jffs2_inodirty *new; | 83 | struct jffs2_inodirty *new; |
84 | 84 | ||
85 | /* Mark the superblock dirty so that kupdated will flush... */ | 85 | /* Mark the superblock dirty so that kupdated will flush... */ |
86 | OFNI_BS_2SFFJ(c)->s_dirt = 1; | 86 | jffs2_erase_pending_trigger(c); |
87 | 87 | ||
88 | if (jffs2_wbuf_pending_for_ino(c, ino)) | 88 | if (jffs2_wbuf_pending_for_ino(c, ino)) |
89 | return; | 89 | return; |
@@ -130,7 +130,10 @@ static inline void jffs2_refile_wbuf_blocks(struct jffs2_sb_info *c) | |||
130 | } | 130 | } |
131 | } | 131 | } |
132 | 132 | ||
133 | static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) | 133 | #define REFILE_NOTEMPTY 0 |
134 | #define REFILE_ANYWAY 1 | ||
135 | |||
136 | static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int allow_empty) | ||
134 | { | 137 | { |
135 | D1(printk("About to refile bad block at %08x\n", jeb->offset)); | 138 | D1(printk("About to refile bad block at %08x\n", jeb->offset)); |
136 | 139 | ||
@@ -144,7 +147,7 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
144 | D1(printk("Refiling block at %08x to bad_used_list\n", jeb->offset)); | 147 | D1(printk("Refiling block at %08x to bad_used_list\n", jeb->offset)); |
145 | list_add(&jeb->list, &c->bad_used_list); | 148 | list_add(&jeb->list, &c->bad_used_list); |
146 | } else { | 149 | } else { |
147 | BUG(); | 150 | BUG_ON(allow_empty == REFILE_NOTEMPTY); |
148 | /* It has to have had some nodes or we couldn't be here */ | 151 | /* It has to have had some nodes or we couldn't be here */ |
149 | D1(printk("Refiling block at %08x to erase_pending_list\n", jeb->offset)); | 152 | D1(printk("Refiling block at %08x to erase_pending_list\n", jeb->offset)); |
150 | list_add(&jeb->list, &c->erase_pending_list); | 153 | list_add(&jeb->list, &c->erase_pending_list); |
@@ -179,7 +182,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
179 | 182 | ||
180 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; | 183 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; |
181 | 184 | ||
182 | jffs2_block_refile(c, jeb); | 185 | jffs2_block_refile(c, jeb, REFILE_NOTEMPTY); |
183 | 186 | ||
184 | /* Find the first node to be recovered, by skipping over every | 187 | /* Find the first node to be recovered, by skipping over every |
185 | node which ends before the wbuf starts, or which is obsolete. */ | 188 | node which ends before the wbuf starts, or which is obsolete. */ |
@@ -264,17 +267,16 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
264 | ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len); | 267 | ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len); |
265 | if (ret) { | 268 | if (ret) { |
266 | printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n"); | 269 | printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n"); |
267 | if (buf) | 270 | kfree(buf); |
268 | kfree(buf); | ||
269 | return; | 271 | return; |
270 | } | 272 | } |
271 | if (end-start >= c->wbuf_pagesize) { | 273 | if (end-start >= c->wbuf_pagesize) { |
272 | /* Need to do another write immediately. This, btw, | 274 | /* Need to do another write immediately, but it's possible |
273 | means that we'll be writing from 'buf' and not from | 275 | that this is just because the wbuf itself is completely |
274 | the wbuf. Since if we're writing from the wbuf there | 276 | full, and there's nothing earlier read back from the |
275 | won't be more than a wbuf full of data, now will | 277 | flash. Hence 'buf' isn't necessarily what we're writing |
276 | there? :) */ | 278 | from. */ |
277 | 279 | unsigned char *rewrite_buf = buf?:c->wbuf; | |
278 | uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize); | 280 | uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize); |
279 | 281 | ||
280 | D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n", | 282 | D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n", |
@@ -292,9 +294,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
292 | #endif | 294 | #endif |
293 | if (jffs2_cleanmarker_oob(c)) | 295 | if (jffs2_cleanmarker_oob(c)) |
294 | ret = c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen, | 296 | ret = c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen, |
295 | buf, NULL, c->oobinfo); | 297 | rewrite_buf, NULL, c->oobinfo); |
296 | else | 298 | else |
297 | ret = c->mtd->write(c->mtd, ofs, towrite, &retlen, buf); | 299 | ret = c->mtd->write(c->mtd, ofs, towrite, &retlen, rewrite_buf); |
298 | 300 | ||
299 | if (ret || retlen != towrite) { | 301 | if (ret || retlen != towrite) { |
300 | /* Argh. We tried. Really we did. */ | 302 | /* Argh. We tried. Really we did. */ |
@@ -321,10 +323,10 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
321 | 323 | ||
322 | c->wbuf_len = (end - start) - towrite; | 324 | c->wbuf_len = (end - start) - towrite; |
323 | c->wbuf_ofs = ofs + towrite; | 325 | c->wbuf_ofs = ofs + towrite; |
324 | memcpy(c->wbuf, buf + towrite, c->wbuf_len); | 326 | memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len); |
325 | /* Don't muck about with c->wbuf_inodes. False positives are harmless. */ | 327 | /* Don't muck about with c->wbuf_inodes. False positives are harmless. */ |
326 | 328 | if (buf) | |
327 | kfree(buf); | 329 | kfree(buf); |
328 | } else { | 330 | } else { |
329 | /* OK, now we're left with the dregs in whichever buffer we're using */ | 331 | /* OK, now we're left with the dregs in whichever buffer we're using */ |
330 | if (buf) { | 332 | if (buf) { |
@@ -413,9 +415,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
413 | int ret; | 415 | int ret; |
414 | size_t retlen; | 416 | size_t retlen; |
415 | 417 | ||
416 | /* Nothing to do if not NAND flash. In particular, we shouldn't | 418 | /* Nothing to do if not write-buffering the flash. In particular, we shouldn't |
417 | del_timer() the timer we never initialised. */ | 419 | del_timer() the timer we never initialised. */ |
418 | if (jffs2_can_mark_obsolete(c)) | 420 | if (!jffs2_is_writebuffered(c)) |
419 | return 0; | 421 | return 0; |
420 | 422 | ||
421 | if (!down_trylock(&c->alloc_sem)) { | 423 | if (!down_trylock(&c->alloc_sem)) { |
@@ -424,7 +426,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
424 | BUG(); | 426 | BUG(); |
425 | } | 427 | } |
426 | 428 | ||
427 | if(!c->wbuf || !c->wbuf_len) | 429 | if (!c->wbuf_len) /* already checked c->wbuf above */ |
428 | return 0; | 430 | return 0; |
429 | 431 | ||
430 | /* claim remaining space on the page | 432 | /* claim remaining space on the page |
@@ -433,7 +435,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
433 | if we have a switch to next page, we will not have | 435 | if we have a switch to next page, we will not have |
434 | enough remaining space for this. | 436 | enough remaining space for this. |
435 | */ | 437 | */ |
436 | if (pad) { | 438 | if (pad && !jffs2_dataflash(c)) { |
437 | c->wbuf_len = PAD(c->wbuf_len); | 439 | c->wbuf_len = PAD(c->wbuf_len); |
438 | 440 | ||
439 | /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR | 441 | /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR |
@@ -484,7 +486,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
484 | spin_lock(&c->erase_completion_lock); | 486 | spin_lock(&c->erase_completion_lock); |
485 | 487 | ||
486 | /* Adjust free size of the block if we padded. */ | 488 | /* Adjust free size of the block if we padded. */ |
487 | if (pad) { | 489 | if (pad && !jffs2_dataflash(c)) { |
488 | struct jffs2_eraseblock *jeb; | 490 | struct jffs2_eraseblock *jeb; |
489 | 491 | ||
490 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; | 492 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; |
@@ -532,6 +534,9 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino) | |||
532 | 534 | ||
533 | D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() called for ino #%u...\n", ino)); | 535 | D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() called for ino #%u...\n", ino)); |
534 | 536 | ||
537 | if (!c->wbuf) | ||
538 | return 0; | ||
539 | |||
535 | down(&c->alloc_sem); | 540 | down(&c->alloc_sem); |
536 | if (!jffs2_wbuf_pending_for_ino(c, ino)) { | 541 | if (!jffs2_wbuf_pending_for_ino(c, ino)) { |
537 | D1(printk(KERN_DEBUG "Ino #%d not pending in wbuf. Returning\n", ino)); | 542 | D1(printk(KERN_DEBUG "Ino #%d not pending in wbuf. Returning\n", ino)); |
@@ -547,6 +552,10 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino) | |||
547 | D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() padding. Not finished checking\n")); | 552 | D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() padding. Not finished checking\n")); |
548 | down_write(&c->wbuf_sem); | 553 | down_write(&c->wbuf_sem); |
549 | ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING); | 554 | ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING); |
555 | /* retry flushing wbuf in case jffs2_wbuf_recover | ||
556 | left some data in the wbuf */ | ||
557 | if (ret) | ||
558 | ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING); | ||
550 | up_write(&c->wbuf_sem); | 559 | up_write(&c->wbuf_sem); |
551 | } else while (old_wbuf_len && | 560 | } else while (old_wbuf_len && |
552 | old_wbuf_ofs == c->wbuf_ofs) { | 561 | old_wbuf_ofs == c->wbuf_ofs) { |
@@ -561,6 +570,10 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino) | |||
561 | down(&c->alloc_sem); | 570 | down(&c->alloc_sem); |
562 | down_write(&c->wbuf_sem); | 571 | down_write(&c->wbuf_sem); |
563 | ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING); | 572 | ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING); |
573 | /* retry flushing wbuf in case jffs2_wbuf_recover | ||
574 | left some data in the wbuf */ | ||
575 | if (ret) | ||
576 | ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING); | ||
564 | up_write(&c->wbuf_sem); | 577 | up_write(&c->wbuf_sem); |
565 | break; | 578 | break; |
566 | } | 579 | } |
@@ -578,15 +591,27 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c) | |||
578 | { | 591 | { |
579 | int ret; | 592 | int ret; |
580 | 593 | ||
594 | if (!c->wbuf) | ||
595 | return 0; | ||
596 | |||
581 | down_write(&c->wbuf_sem); | 597 | down_write(&c->wbuf_sem); |
582 | ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT); | 598 | ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT); |
599 | /* retry - maybe wbuf recover left some data in wbuf. */ | ||
600 | if (ret) | ||
601 | ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT); | ||
583 | up_write(&c->wbuf_sem); | 602 | up_write(&c->wbuf_sem); |
584 | 603 | ||
585 | return ret; | 604 | return ret; |
586 | } | 605 | } |
587 | 606 | ||
607 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | ||
608 | #define PAGE_DIV(x) ( ((unsigned long)(x) / (unsigned long)(c->wbuf_pagesize)) * (unsigned long)(c->wbuf_pagesize) ) | ||
609 | #define PAGE_MOD(x) ( (unsigned long)(x) % (unsigned long)(c->wbuf_pagesize) ) | ||
610 | #else | ||
588 | #define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) ) | 611 | #define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) ) |
589 | #define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) ) | 612 | #define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) ) |
613 | #endif | ||
614 | |||
590 | int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) | 615 | int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) |
591 | { | 616 | { |
592 | struct kvec outvecs[3]; | 617 | struct kvec outvecs[3]; |
@@ -601,7 +626,7 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig | |||
601 | uint32_t outvec_to = to; | 626 | uint32_t outvec_to = to; |
602 | 627 | ||
603 | /* If not NAND flash, don't bother */ | 628 | /* If not NAND flash, don't bother */ |
604 | if (!c->wbuf) | 629 | if (!jffs2_is_writebuffered(c)) |
605 | return jffs2_flash_direct_writev(c, invecs, count, to, retlen); | 630 | return jffs2_flash_direct_writev(c, invecs, count, to, retlen); |
606 | 631 | ||
607 | down_write(&c->wbuf_sem); | 632 | down_write(&c->wbuf_sem); |
@@ -630,7 +655,7 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig | |||
630 | erase block. Anything else, and you die. | 655 | erase block. Anything else, and you die. |
631 | New block starts at xxx000c (0-b = block header) | 656 | New block starts at xxx000c (0-b = block header) |
632 | */ | 657 | */ |
633 | if ( (to & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) ) { | 658 | if (SECTOR_ADDR(to) != SECTOR_ADDR(c->wbuf_ofs)) { |
634 | /* It's a write to a new block */ | 659 | /* It's a write to a new block */ |
635 | if (c->wbuf_len) { | 660 | if (c->wbuf_len) { |
636 | D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx causes flush of wbuf at 0x%08x\n", (unsigned long)to, c->wbuf_ofs)); | 661 | D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx causes flush of wbuf at 0x%08x\n", (unsigned long)to, c->wbuf_ofs)); |
@@ -762,9 +787,18 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig | |||
762 | 787 | ||
763 | if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) { | 788 | if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) { |
764 | /* At this point we have no problem, | 789 | /* At this point we have no problem, |
765 | c->wbuf is empty. | 790 | c->wbuf is empty. However refile nextblock to avoid |
791 | writing again to same address. | ||
766 | */ | 792 | */ |
767 | *retlen = donelen; | 793 | struct jffs2_eraseblock *jeb; |
794 | |||
795 | spin_lock(&c->erase_completion_lock); | ||
796 | |||
797 | jeb = &c->blocks[outvec_to / c->sector_size]; | ||
798 | jffs2_block_refile(c, jeb, REFILE_ANYWAY); | ||
799 | |||
800 | *retlen = 0; | ||
801 | spin_unlock(&c->erase_completion_lock); | ||
768 | goto exit; | 802 | goto exit; |
769 | } | 803 | } |
770 | 804 | ||
@@ -819,7 +853,7 @@ int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *r | |||
819 | { | 853 | { |
820 | struct kvec vecs[1]; | 854 | struct kvec vecs[1]; |
821 | 855 | ||
822 | if (jffs2_can_mark_obsolete(c)) | 856 | if (!jffs2_is_writebuffered(c)) |
823 | return c->mtd->write(c->mtd, ofs, len, retlen, buf); | 857 | return c->mtd->write(c->mtd, ofs, len, retlen, buf); |
824 | 858 | ||
825 | vecs[0].iov_base = (unsigned char *) buf; | 859 | vecs[0].iov_base = (unsigned char *) buf; |
@@ -835,39 +869,38 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re | |||
835 | loff_t orbf = 0, owbf = 0, lwbf = 0; | 869 | loff_t orbf = 0, owbf = 0, lwbf = 0; |
836 | int ret; | 870 | int ret; |
837 | 871 | ||
838 | /* Read flash */ | 872 | if (!jffs2_is_writebuffered(c)) |
839 | if (!jffs2_can_mark_obsolete(c)) { | ||
840 | down_read(&c->wbuf_sem); | ||
841 | |||
842 | if (jffs2_cleanmarker_oob(c)) | ||
843 | ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo); | ||
844 | else | ||
845 | ret = c->mtd->read(c->mtd, ofs, len, retlen, buf); | ||
846 | |||
847 | if ( (ret == -EBADMSG) && (*retlen == len) ) { | ||
848 | printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n", | ||
849 | len, ofs); | ||
850 | /* | ||
851 | * We have the raw data without ECC correction in the buffer, maybe | ||
852 | * we are lucky and all data or parts are correct. We check the node. | ||
853 | * If data are corrupted node check will sort it out. | ||
854 | * We keep this block, it will fail on write or erase and the we | ||
855 | * mark it bad. Or should we do that now? But we should give him a chance. | ||
856 | * Maybe we had a system crash or power loss before the ecc write or | ||
857 | * a erase was completed. | ||
858 | * So we return success. :) | ||
859 | */ | ||
860 | ret = 0; | ||
861 | } | ||
862 | } else | ||
863 | return c->mtd->read(c->mtd, ofs, len, retlen, buf); | 873 | return c->mtd->read(c->mtd, ofs, len, retlen, buf); |
864 | 874 | ||
875 | /* Read flash */ | ||
876 | down_read(&c->wbuf_sem); | ||
877 | if (jffs2_cleanmarker_oob(c)) | ||
878 | ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo); | ||
879 | else | ||
880 | ret = c->mtd->read(c->mtd, ofs, len, retlen, buf); | ||
881 | |||
882 | if ( (ret == -EBADMSG) && (*retlen == len) ) { | ||
883 | printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n", | ||
884 | len, ofs); | ||
885 | /* | ||
886 | * We have the raw data without ECC correction in the buffer, maybe | ||
887 | * we are lucky and all data or parts are correct. We check the node. | ||
888 | * If data are corrupted node check will sort it out. | ||
889 | * We keep this block, it will fail on write or erase and the we | ||
890 | * mark it bad. Or should we do that now? But we should give him a chance. | ||
891 | * Maybe we had a system crash or power loss before the ecc write or | ||
892 | * a erase was completed. | ||
893 | * So we return success. :) | ||
894 | */ | ||
895 | ret = 0; | ||
896 | } | ||
897 | |||
865 | /* if no writebuffer available or write buffer empty, return */ | 898 | /* if no writebuffer available or write buffer empty, return */ |
866 | if (!c->wbuf_pagesize || !c->wbuf_len) | 899 | if (!c->wbuf_pagesize || !c->wbuf_len) |
867 | goto exit; | 900 | goto exit; |
868 | 901 | ||
869 | /* if we read in a different block, return */ | 902 | /* if we read in a different block, return */ |
870 | if ( (ofs & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) ) | 903 | if (SECTOR_ADDR(ofs) != SECTOR_ADDR(c->wbuf_ofs)) |
871 | goto exit; | 904 | goto exit; |
872 | 905 | ||
873 | if (ofs >= c->wbuf_ofs) { | 906 | if (ofs >= c->wbuf_ofs) { |
@@ -1161,7 +1194,27 @@ void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c) | |||
1161 | kfree(c->wbuf); | 1194 | kfree(c->wbuf); |
1162 | } | 1195 | } |
1163 | 1196 | ||
1164 | #ifdef CONFIG_JFFS2_FS_NOR_ECC | 1197 | int jffs2_dataflash_setup(struct jffs2_sb_info *c) { |
1198 | c->cleanmarker_size = 0; /* No cleanmarkers needed */ | ||
1199 | |||
1200 | /* Initialize write buffer */ | ||
1201 | init_rwsem(&c->wbuf_sem); | ||
1202 | c->wbuf_pagesize = c->sector_size; | ||
1203 | c->wbuf_ofs = 0xFFFFFFFF; | ||
1204 | |||
1205 | c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); | ||
1206 | if (!c->wbuf) | ||
1207 | return -ENOMEM; | ||
1208 | |||
1209 | printk(KERN_INFO "JFFS2 write-buffering enabled (%i)\n", c->wbuf_pagesize); | ||
1210 | |||
1211 | return 0; | ||
1212 | } | ||
1213 | |||
1214 | void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) { | ||
1215 | kfree(c->wbuf); | ||
1216 | } | ||
1217 | |||
1165 | int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) { | 1218 | int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) { |
1166 | /* Cleanmarker is actually larger on the flashes */ | 1219 | /* Cleanmarker is actually larger on the flashes */ |
1167 | c->cleanmarker_size = 16; | 1220 | c->cleanmarker_size = 16; |
@@ -1181,4 +1234,3 @@ int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) { | |||
1181 | void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c) { | 1234 | void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c) { |
1182 | kfree(c->wbuf); | 1235 | kfree(c->wbuf); |
1183 | } | 1236 | } |
1184 | #endif | ||