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 | |
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')
-rw-r--r-- | fs/jffs2/os-linux.h | 6 | ||||
-rw-r--r-- | fs/jffs2/scan.c | 6 | ||||
-rw-r--r-- | fs/jffs2/wbuf.c | 50 |
3 files changed, 40 insertions, 22 deletions
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 48ad4202fbb1..04d4167ab252 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h | |||
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | * For licensing information, see the file 'LICENCE' in this directory. | 8 | * For licensing information, see the file 'LICENCE' in this directory. |
9 | * | 9 | * |
10 | * $Id: os-linux.h,v 1.63 2005/09/21 11:55:21 dedekind Exp $ | 10 | * $Id: os-linux.h,v 1.64 2005/09/30 13:59:13 dedekind Exp $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
@@ -65,8 +65,9 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) | |||
65 | 65 | ||
66 | #define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY) | 66 | #define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY) |
67 | 67 | ||
68 | #define SECTOR_ADDR(x) ( (((unsigned long)(x) / c->sector_size) * c->sector_size) ) | ||
68 | #ifndef CONFIG_JFFS2_FS_WRITEBUFFER | 69 | #ifndef CONFIG_JFFS2_FS_WRITEBUFFER |
69 | #define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) ) | 70 | |
70 | 71 | ||
71 | #ifdef CONFIG_JFFS2_SUMMARY | 72 | #ifdef CONFIG_JFFS2_SUMMARY |
72 | #define jffs2_can_mark_obsolete(c) (0) | 73 | #define jffs2_can_mark_obsolete(c) (0) |
@@ -102,7 +103,6 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) | |||
102 | #else /* NAND and/or ECC'd NOR support present */ | 103 | #else /* NAND and/or ECC'd NOR support present */ |
103 | 104 | ||
104 | #define jffs2_is_writebuffered(c) (c->wbuf != NULL) | 105 | #define jffs2_is_writebuffered(c) (c->wbuf != NULL) |
105 | #define SECTOR_ADDR(x) ( ((unsigned long)(x) / (unsigned long)(c->sector_size)) * c->sector_size ) | ||
106 | 106 | ||
107 | #ifdef CONFIG_JFFS2_SUMMARY | 107 | #ifdef CONFIG_JFFS2_SUMMARY |
108 | #define jffs2_can_mark_obsolete(c) (0) | 108 | #define jffs2_can_mark_obsolete(c) (0) |
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 8df7456472b8..805a166469d2 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | * For licensing information, see the file 'LICENCE' in this directory. | 8 | * For licensing information, see the file 'LICENCE' in this directory. |
9 | * | 9 | * |
10 | * $Id: scan.c,v 1.124 2005/09/21 13:05:22 dedekind Exp $ | 10 | * $Id: scan.c,v 1.125 2005/09/30 13:59:13 dedekind Exp $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
@@ -233,12 +233,12 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) | |||
233 | c->nextblock->dirty_size = 0; | 233 | c->nextblock->dirty_size = 0; |
234 | } | 234 | } |
235 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | 235 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER |
236 | if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) { | 236 | if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) { |
237 | /* If we're going to start writing into a block which already | 237 | /* If we're going to start writing into a block which already |
238 | contains data, and the end of the data isn't page-aligned, | 238 | contains data, and the end of the data isn't page-aligned, |
239 | skip a little and align it. */ | 239 | skip a little and align it. */ |
240 | 240 | ||
241 | uint32_t skip = c->nextblock->free_size & (c->wbuf_pagesize-1); | 241 | uint32_t skip = c->nextblock->free_size % c->wbuf_pagesize; |
242 | 242 | ||
243 | D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n", | 243 | D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n", |
244 | skip)); | 244 | skip)); |
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 | } |