diff options
author | Artem B. Bityutskiy <dedekind@infradead.org> | 2005-09-30 09:59:17 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@mtd.linutronix.de> | 2005-11-06 17:01:48 -0500 |
commit | daba5cc4bcd025a9b4fd02a9117c71bfd400d811 (patch) | |
tree | da74b64b3bbd4ae215ced6d2d54abe7fdf83818e /fs/jffs2/wbuf.c | |
parent | 83a368380e172c1b2e9fd6ec2a62e457684adf0c (diff) |
[JFFS2] Fix dataflash support
- assume wbuf may be of size which is not power of 2
- don't make strange assumption about not padding wbuf for DataFlash
- use wbuf = DataFlash page and eraseblock >= 8 Dataflash pages
From: Peter Menzebach <pm-mtd@mw-itcon.de>
Acked-by: Artem B. Bityutskiy <dedekind@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'fs/jffs2/wbuf.c')
-rw-r--r-- | fs/jffs2/wbuf.c | 50 |
1 files changed, 34 insertions, 16 deletions
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 11e05bc014f1..44d8a894a41b 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.99 2005/09/21 16:11:04 dedekind Exp $ | 12 | * $Id: wbuf.c,v 1.100 2005/09/30 13:59:13 dedekind Exp $ |
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
@@ -30,6 +30,9 @@ | |||
30 | static unsigned char *brokenbuf; | 30 | static unsigned char *brokenbuf; |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #define PAGE_DIV(x) ( ((unsigned long)(x) / (unsigned long)(c->wbuf_pagesize)) * (unsigned long)(c->wbuf_pagesize) ) | ||
34 | #define PAGE_MOD(x) ( (unsigned long)(x) % (unsigned long)(c->wbuf_pagesize) ) | ||
35 | |||
33 | /* max. erase failures before we mark a block bad */ | 36 | /* max. erase failures before we mark a block bad */ |
34 | #define MAX_ERASE_FAILURES 2 | 37 | #define MAX_ERASE_FAILURES 2 |
35 | 38 | ||
@@ -433,7 +436,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 | 436 | if we have a switch to next page, we will not have |
434 | enough remaining space for this. | 437 | enough remaining space for this. |
435 | */ | 438 | */ |
436 | if (pad && !jffs2_dataflash(c)) { | 439 | if (pad ) { |
437 | c->wbuf_len = PAD(c->wbuf_len); | 440 | c->wbuf_len = PAD(c->wbuf_len); |
438 | 441 | ||
439 | /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR | 442 | /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR |
@@ -482,9 +485,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
482 | } | 485 | } |
483 | 486 | ||
484 | spin_lock(&c->erase_completion_lock); | 487 | spin_lock(&c->erase_completion_lock); |
485 | 488 | ||
486 | /* Adjust free size of the block if we padded. */ | 489 | /* Adjust free size of the block if we padded. */ |
487 | if (pad && !jffs2_dataflash(c)) { | 490 | if (pad) { |
488 | struct jffs2_eraseblock *jeb; | 491 | struct jffs2_eraseblock *jeb; |
489 | 492 | ||
490 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; | 493 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; |
@@ -601,15 +604,6 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c) | |||
601 | 604 | ||
602 | return ret; | 605 | return ret; |
603 | } | 606 | } |
604 | |||
605 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | ||
606 | #define PAGE_DIV(x) ( ((unsigned long)(x) / (unsigned long)(c->wbuf_pagesize)) * (unsigned long)(c->wbuf_pagesize) ) | ||
607 | #define PAGE_MOD(x) ( (unsigned long)(x) % (unsigned long)(c->wbuf_pagesize) ) | ||
608 | #else | ||
609 | #define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) ) | ||
610 | #define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) ) | ||
611 | #endif | ||
612 | |||
613 | 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) | 607 | 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) |
614 | { | 608 | { |
615 | struct kvec outvecs[3]; | 609 | struct kvec outvecs[3]; |
@@ -1203,14 +1197,38 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { | |||
1203 | 1197 | ||
1204 | /* Initialize write buffer */ | 1198 | /* Initialize write buffer */ |
1205 | init_rwsem(&c->wbuf_sem); | 1199 | init_rwsem(&c->wbuf_sem); |
1206 | c->wbuf_pagesize = c->sector_size; | 1200 | |
1207 | c->wbuf_ofs = 0xFFFFFFFF; | 1201 | |
1202 | c->wbuf_pagesize = c->mtd->erasesize; | ||
1203 | |||
1204 | /* Find a suitable c->sector_size | ||
1205 | * - Not too much sectors | ||
1206 | * - Sectors have to be at least 4 K + some bytes | ||
1207 | * - All known dataflashes have erase sizes of 528 or 1056 | ||
1208 | * - we take at least 8 eraseblocks and want to have at least 8K size | ||
1209 | * - The concatenation should be a power of 2 | ||
1210 | */ | ||
1211 | |||
1212 | c->sector_size = 8 * c->mtd->erasesize; | ||
1213 | |||
1214 | while (c->sector_size < 8192) { | ||
1215 | c->sector_size *= 2; | ||
1216 | } | ||
1217 | |||
1218 | /* It may be necessary to adjust the flash size */ | ||
1219 | c->flash_size = c->mtd->size; | ||
1208 | 1220 | ||
1221 | if ((c->flash_size % c->sector_size) != 0) { | ||
1222 | c->flash_size = (c->flash_size / c->sector_size) * c->sector_size; | ||
1223 | printk(KERN_WARNING "JFFS2 flash size adjusted to %dKiB\n", c->flash_size); | ||
1224 | }; | ||
1225 | |||
1226 | c->wbuf_ofs = 0xFFFFFFFF; | ||
1209 | c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); | 1227 | c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); |
1210 | if (!c->wbuf) | 1228 | if (!c->wbuf) |
1211 | return -ENOMEM; | 1229 | return -ENOMEM; |
1212 | 1230 | ||
1213 | printk(KERN_INFO "JFFS2 write-buffering enabled (%i)\n", c->wbuf_pagesize); | 1231 | printk(KERN_INFO "JFFS2 write-buffering enabled buffer (%d) erasesize (%d)\n", c->wbuf_pagesize, c->sector_size); |
1214 | 1232 | ||
1215 | return 0; | 1233 | return 0; |
1216 | } | 1234 | } |