aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAndrew Victor <andrew@sanpeople.com>2005-02-09 04:17:45 -0500
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-05-23 06:28:03 -0400
commit8f15fd55f9bf266139b10850947e19c4e3f4e9b7 (patch)
tree3df936efbffbbd6c20dd75f51780ac37458285ff /fs
parent3be36675d41a30ed3b192f92684f1417aa0f8bfe (diff)
[JFFS2] Add support for JFFS2-on-Dataflash devices.
For Dataflash, can_mark_obsolete = false and the NAND write buffering code (wbuf.c) is used. Since the DataFlash chip will automatically erase pages when writing, the cleanmarkers are not needed - so cleanmarker_oob = false and cleanmarker_size = 0 DataFlash page-sizes are not a power of two (they're multiples of 528 bytes). The SECTOR_ADDR macro (added in the previous core patch) is replaced with a (slower) div/mod version if CONFIG_JFFS2_FS_DATAFLASH is selected. Signed-off-by: Andrew Victor <andrew@sanpeople.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig7
-rw-r--r--fs/jffs2/Makefile3
-rw-r--r--fs/jffs2/erase.c13
-rw-r--r--fs/jffs2/fs.c21
-rw-r--r--fs/jffs2/os-linux.h18
-rw-r--r--fs/jffs2/scan.c11
-rw-r--r--fs/jffs2/wbuf.c35
7 files changed, 94 insertions, 14 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index 6a4ad4bb7a54..07835d24c785 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1084,6 +1084,13 @@ config JFFS2_FS_NOR_ECC
1084 ECC for JFFS2. This type of flash chip is not common, however it is 1084 ECC for JFFS2. This type of flash chip is not common, however it is
1085 available from ST Microelectronics. 1085 available from ST Microelectronics.
1086 1086
1087config JFFS2_FS_DATAFLASH
1088 bool "JFFS2 support for DataFlash (EXPERIMENTAL)"
1089 depends on JFFS2_FS && EXPERIMENTAL
1090 default n
1091 help
1092 This enables the experimental support for JFFS2 on DataFlash devices.
1093
1087config JFFS2_COMPRESSION_OPTIONS 1094config JFFS2_COMPRESSION_OPTIONS
1088 bool "Advanced compression options for JFFS2" 1095 bool "Advanced compression options for JFFS2"
1089 depends on JFFS2_FS 1096 depends on JFFS2_FS
diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile
index e3c38ccf9c7d..6c2ebe176b40 100644
--- a/fs/jffs2/Makefile
+++ b/fs/jffs2/Makefile
@@ -1,7 +1,7 @@
1# 1#
2# Makefile for the Linux Journalling Flash File System v2 (JFFS2) 2# Makefile for the Linux Journalling Flash File System v2 (JFFS2)
3# 3#
4# $Id: Makefile.common,v 1.7 2004/11/03 12:57:38 jwboyer Exp $ 4# $Id: Makefile.common,v 1.8 2005/02/09 09:17:40 pavlov Exp $
5# 5#
6 6
7obj-$(CONFIG_JFFS2_FS) += jffs2.o 7obj-$(CONFIG_JFFS2_FS) += jffs2.o
@@ -13,6 +13,7 @@ jffs2-y += super.o
13 13
14jffs2-$(CONFIG_JFFS2_FS_NAND) += wbuf.o 14jffs2-$(CONFIG_JFFS2_FS_NAND) += wbuf.o
15jffs2-$(CONFIG_JFFS2_FS_NOR_ECC) += wbuf.o 15jffs2-$(CONFIG_JFFS2_FS_NOR_ECC) += wbuf.o
16jffs2-$(CONFIG_JFFS2_FS_DATAFLASH) += wbuf.o
16jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o 17jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o
17jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o 18jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o
18jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o 19jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index ae858f878875..a3c6cc150497 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.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: erase.c,v 1.70 2005/02/09 09:09:01 pavlov Exp $ 10 * $Id: erase.c,v 1.71 2005/02/09 09:17:40 pavlov Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -310,7 +310,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
310 int ret; 310 int ret;
311 uint32_t bad_offset; 311 uint32_t bad_offset;
312 312
313 if (!jffs2_cleanmarker_oob(c)) { 313 if ((!jffs2_cleanmarker_oob(c)) && (c->cleanmarker_size > 0)) {
314 marker_ref = jffs2_alloc_raw_node_ref(); 314 marker_ref = jffs2_alloc_raw_node_ref();
315 if (!marker_ref) { 315 if (!marker_ref) {
316 printk(KERN_WARNING "Failed to allocate raw node ref for clean marker\n"); 316 printk(KERN_WARNING "Failed to allocate raw node ref for clean marker\n");
@@ -351,7 +351,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
351 bad_offset += i; 351 bad_offset += i;
352 printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n", datum, bad_offset); 352 printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n", datum, bad_offset);
353 bad: 353 bad:
354 if (!jffs2_cleanmarker_oob(c)) 354 if ((!jffs2_cleanmarker_oob(c)) && (c->cleanmarker_size > 0))
355 jffs2_free_raw_node_ref(marker_ref); 355 jffs2_free_raw_node_ref(marker_ref);
356 kfree(ebuf); 356 kfree(ebuf);
357 bad2: 357 bad2:
@@ -387,6 +387,13 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
387 jeb->used_size = 0; 387 jeb->used_size = 0;
388 jeb->dirty_size = 0; 388 jeb->dirty_size = 0;
389 jeb->wasted_size = 0; 389 jeb->wasted_size = 0;
390 } else if (c->cleanmarker_size == 0) {
391 jeb->first_node = jeb->last_node = NULL;
392
393 jeb->free_size = c->sector_size;
394 jeb->used_size = 0;
395 jeb->dirty_size = 0;
396 jeb->wasted_size = 0;
390 } else { 397 } else {
391 struct kvec vecs[1]; 398 struct kvec vecs[1];
392 struct jffs2_unknown_node marker = { 399 struct jffs2_unknown_node marker = {
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 30ab233fe423..5b7c960a0475 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.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: fs.c,v 1.51 2004/11/28 12:19:37 dedekind Exp $ 10 * $Id: fs.c,v 1.52 2005/02/09 09:17:40 pavlov Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -456,6 +456,12 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
456 return -EINVAL; 456 return -EINVAL;
457 } 457 }
458#endif 458#endif
459#ifndef CONFIG_JFFS2_FS_DATAFLASH
460 if (c->mtd->type == MTD_DATAFLASH) {
461 printk(KERN_ERR "jffs2: Cannot operate on DataFlash unless jffs2 DataFlash support is compiled in.\n");
462 return -EINVAL;
463 }
464#endif
459 465
460 c->flash_size = c->mtd->size; 466 c->flash_size = c->mtd->size;
461 467
@@ -661,6 +667,14 @@ static int jffs2_flash_setup(struct jffs2_sb_info *c) {
661 if (ret) 667 if (ret)
662 return ret; 668 return ret;
663 } 669 }
670
671 /* and Dataflash */
672 if (jffs2_dataflash(c)) {
673 ret = jffs2_dataflash_setup(c);
674 if (ret)
675 return ret;
676 }
677
664 return ret; 678 return ret;
665} 679}
666 680
@@ -674,4 +688,9 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c) {
674 if (jffs2_nor_ecc(c)) { 688 if (jffs2_nor_ecc(c)) {
675 jffs2_nor_ecc_flash_cleanup(c); 689 jffs2_nor_ecc_flash_cleanup(c);
676 } 690 }
691
692 /* and DataFlash */
693 if (jffs2_dataflash(c)) {
694 jffs2_dataflash_cleanup(c);
695 }
677} 696}
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 0412416d1f2d..af27b84007a1 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.52 2005/02/09 09:09:01 pavlov Exp $ 10 * $Id: os-linux.h,v 1.53 2005/02/09 09:17:41 pavlov Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -97,12 +97,16 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
97#endif 97#endif
98} 98}
99 99
100#ifdef CONFIG_JFFS2_FS_DATAFLASH
101#define SECTOR_ADDR(x) ( ((unsigned long)(x) / (unsigned long)(c->sector_size)) * c->sector_size )
102#else
100#define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) ) 103#define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) )
104#endif
101 105
102#define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY) 106#define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY)
103#define jffs2_is_writebuffered(c) (c->wbuf != NULL) 107#define jffs2_is_writebuffered(c) (c->wbuf != NULL)
104 108
105#if (!defined CONFIG_JFFS2_FS_NAND && !defined CONFIG_JFFS2_FS_NOR_ECC) 109#if (!defined CONFIG_JFFS2_FS_NAND && !defined CONFIG_JFFS2_FS_NOR_ECC && !defined CONFIG_JFFS2_FS_DATAFLASH)
106#define jffs2_can_mark_obsolete(c) (1) 110#define jffs2_can_mark_obsolete(c) (1)
107#define jffs2_cleanmarker_oob(c) (0) 111#define jffs2_cleanmarker_oob(c) (0)
108#define jffs2_write_nand_cleanmarker(c,jeb) (-EIO) 112#define jffs2_write_nand_cleanmarker(c,jeb) (-EIO)
@@ -119,6 +123,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
119#define jffs2_wbuf_timeout NULL 123#define jffs2_wbuf_timeout NULL
120#define jffs2_wbuf_process NULL 124#define jffs2_wbuf_process NULL
121#define jffs2_nor_ecc(c) (0) 125#define jffs2_nor_ecc(c) (0)
126#define jffs2_dataflash(c) (0)
122#define jffs2_nor_ecc_flash_setup(c) (0) 127#define jffs2_nor_ecc_flash_setup(c) (0)
123#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0) 128#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0)
124 129
@@ -154,6 +159,15 @@ void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c);
154#define jffs2_nor_ecc_flash_setup(c) (0) 159#define jffs2_nor_ecc_flash_setup(c) (0)
155#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0) 160#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0)
156#endif /* NOR ECC */ 161#endif /* NOR ECC */
162#ifdef CONFIG_JFFS2_FS_DATAFLASH
163#define jffs2_dataflash(c) (c->mtd->type == MTD_DATAFLASH)
164int jffs2_dataflash_setup(struct jffs2_sb_info *c);
165void jffs2_dataflash_cleanup(struct jffs2_sb_info *c);
166#else
167#define jffs2_dataflash(c) (0)
168#define jffs2_dataflash_setup(c) (0)
169#define jffs2_dataflash_cleanup(c) do {} while (0)
170#endif /* DATAFLASH */
157#endif /* NAND */ 171#endif /* NAND */
158 172
159/* erase.c */ 173/* erase.c */
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 76859ff53437..e8c43746c82e 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.116 2005/02/09 09:09:02 pavlov Exp $ 10 * $Id: scan.c,v 1.117 2005/02/09 09:17:41 pavlov Exp $
11 * 11 *
12 */ 12 */
13#include <linux/kernel.h> 13#include <linux/kernel.h>
@@ -68,7 +68,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
68static inline int min_free(struct jffs2_sb_info *c) 68static inline int min_free(struct jffs2_sb_info *c)
69{ 69{
70 uint32_t min = 2 * sizeof(struct jffs2_raw_inode); 70 uint32_t min = 2 * sizeof(struct jffs2_raw_inode);
71#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC 71#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC || defined CONFIG_JFFS2_FS_DATAFLASH
72 if (!jffs2_can_mark_obsolete(c) && min < c->wbuf_pagesize) 72 if (!jffs2_can_mark_obsolete(c) && min < c->wbuf_pagesize)
73 return c->wbuf_pagesize; 73 return c->wbuf_pagesize;
74#endif 74#endif
@@ -228,7 +228,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
228 c->dirty_size -= c->nextblock->dirty_size; 228 c->dirty_size -= c->nextblock->dirty_size;
229 c->nextblock->dirty_size = 0; 229 c->nextblock->dirty_size = 0;
230 } 230 }
231#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC 231#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC || defined CONFIG_JFFS2_FS_DATAFLASH
232 if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) { 232 if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) {
233 /* If we're going to start writing into a block which already 233 /* If we're going to start writing into a block which already
234 contains data, and the end of the data isn't page-aligned, 234 contains data, and the end of the data isn't page-aligned,
@@ -351,7 +351,10 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
351 } 351 }
352#endif 352#endif
353 D1(printk(KERN_DEBUG "Block at 0x%08x is empty (erased)\n", jeb->offset)); 353 D1(printk(KERN_DEBUG "Block at 0x%08x is empty (erased)\n", jeb->offset));
354 return BLK_STATE_ALLFF; /* OK to erase if all blocks are like this */ 354 if (c->cleanmarker_size == 0)
355 return BLK_STATE_CLEANMARKER; /* don't bother with re-erase */
356 else
357 return BLK_STATE_ALLFF; /* OK to erase if all blocks are like this */
355 } 358 }
356 if (ofs) { 359 if (ofs) {
357 D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset, 360 D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset,
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 894dea88678d..a35e007e5bf8 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.87 2005/02/09 09:09:02 pavlov Exp $ 12 * $Id: wbuf.c,v 1.88 2005/02/09 09:17:41 pavlov Exp $
13 * 13 *
14 */ 14 */
15 15
@@ -435,7 +435,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
435 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
436 enough remaining space for this. 436 enough remaining space for this.
437 */ 437 */
438 if (pad) { 438 if (pad && !jffs2_dataflash(c)) {
439 c->wbuf_len = PAD(c->wbuf_len); 439 c->wbuf_len = PAD(c->wbuf_len);
440 440
441 /* 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
@@ -486,7 +486,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
486 spin_lock(&c->erase_completion_lock); 486 spin_lock(&c->erase_completion_lock);
487 487
488 /* Adjust free size of the block if we padded. */ 488 /* Adjust free size of the block if we padded. */
489 if (pad) { 489 if (pad && !jffs2_dataflash(c)) {
490 struct jffs2_eraseblock *jeb; 490 struct jffs2_eraseblock *jeb;
491 491
492 jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; 492 jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
@@ -604,8 +604,14 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c)
604 return ret; 604 return ret;
605} 605}
606 606
607#ifdef CONFIG_JFFS2_FS_DATAFLASH
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
607#define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) ) 611#define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) )
608#define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) ) 612#define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) )
613#endif
614
609int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) 615int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino)
610{ 616{
611 struct kvec outvecs[3]; 617 struct kvec outvecs[3];
@@ -1192,6 +1198,29 @@ void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
1192 kfree(c->wbuf); 1198 kfree(c->wbuf);
1193} 1199}
1194 1200
1201#ifdef CONFIG_JFFS2_FS_DATAFLASH
1202int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
1203 c->cleanmarker_size = 0; /* No cleanmarkers needed */
1204
1205 /* Initialize write buffer */
1206 init_rwsem(&c->wbuf_sem);
1207 c->wbuf_pagesize = c->sector_size;
1208 c->wbuf_ofs = 0xFFFFFFFF;
1209
1210 c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
1211 if (!c->wbuf)
1212 return -ENOMEM;
1213
1214 printk(KERN_INFO "JFFS2 write-buffering enabled (%i)\n", c->wbuf_pagesize);
1215
1216 return 0;
1217}
1218
1219void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) {
1220 kfree(c->wbuf);
1221}
1222#endif
1223
1195#ifdef CONFIG_JFFS2_FS_NOR_ECC 1224#ifdef CONFIG_JFFS2_FS_NOR_ECC
1196int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) { 1225int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) {
1197 /* Cleanmarker is actually larger on the flashes */ 1226 /* Cleanmarker is actually larger on the flashes */