Commit daba5cc4 authored by Artem B. Bityutskiy's avatar Artem B. Bityutskiy Committed by Thomas Gleixner

[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: default avatarArtem B. Bityutskiy <dedekind@infradead.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 83a36838
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: os-linux.h,v 1.63 2005/09/21 11:55:21 dedekind Exp $ * $Id: os-linux.h,v 1.64 2005/09/30 13:59:13 dedekind Exp $
* *
*/ */
...@@ -65,8 +65,9 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) ...@@ -65,8 +65,9 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
#define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY) #define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY)
#define SECTOR_ADDR(x) ( (((unsigned long)(x) / c->sector_size) * c->sector_size) )
#ifndef CONFIG_JFFS2_FS_WRITEBUFFER #ifndef CONFIG_JFFS2_FS_WRITEBUFFER
#define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) )
#ifdef CONFIG_JFFS2_SUMMARY #ifdef CONFIG_JFFS2_SUMMARY
#define jffs2_can_mark_obsolete(c) (0) #define jffs2_can_mark_obsolete(c) (0)
...@@ -102,7 +103,6 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) ...@@ -102,7 +103,6 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
#else /* NAND and/or ECC'd NOR support present */ #else /* NAND and/or ECC'd NOR support present */
#define jffs2_is_writebuffered(c) (c->wbuf != NULL) #define jffs2_is_writebuffered(c) (c->wbuf != NULL)
#define SECTOR_ADDR(x) ( ((unsigned long)(x) / (unsigned long)(c->sector_size)) * c->sector_size )
#ifdef CONFIG_JFFS2_SUMMARY #ifdef CONFIG_JFFS2_SUMMARY
#define jffs2_can_mark_obsolete(c) (0) #define jffs2_can_mark_obsolete(c) (0)
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: scan.c,v 1.124 2005/09/21 13:05:22 dedekind Exp $ * $Id: scan.c,v 1.125 2005/09/30 13:59:13 dedekind Exp $
* *
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -233,12 +233,12 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) ...@@ -233,12 +233,12 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
c->nextblock->dirty_size = 0; c->nextblock->dirty_size = 0;
} }
#ifdef CONFIG_JFFS2_FS_WRITEBUFFER #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) { if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) {
/* If we're going to start writing into a block which already /* If we're going to start writing into a block which already
contains data, and the end of the data isn't page-aligned, contains data, and the end of the data isn't page-aligned,
skip a little and align it. */ skip a little and align it. */
uint32_t skip = c->nextblock->free_size & (c->wbuf_pagesize-1); uint32_t skip = c->nextblock->free_size % c->wbuf_pagesize;
D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n", D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n",
skip)); skip));
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: wbuf.c,v 1.99 2005/09/21 16:11:04 dedekind Exp $ * $Id: wbuf.c,v 1.100 2005/09/30 13:59:13 dedekind Exp $
* *
*/ */
...@@ -30,6 +30,9 @@ ...@@ -30,6 +30,9 @@
static unsigned char *brokenbuf; static unsigned char *brokenbuf;
#endif #endif
#define PAGE_DIV(x) ( ((unsigned long)(x) / (unsigned long)(c->wbuf_pagesize)) * (unsigned long)(c->wbuf_pagesize) )
#define PAGE_MOD(x) ( (unsigned long)(x) % (unsigned long)(c->wbuf_pagesize) )
/* max. erase failures before we mark a block bad */ /* max. erase failures before we mark a block bad */
#define MAX_ERASE_FAILURES 2 #define MAX_ERASE_FAILURES 2
...@@ -433,7 +436,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) ...@@ -433,7 +436,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
if we have a switch to next page, we will not have if we have a switch to next page, we will not have
enough remaining space for this. enough remaining space for this.
*/ */
if (pad && !jffs2_dataflash(c)) { if (pad ) {
c->wbuf_len = PAD(c->wbuf_len); c->wbuf_len = PAD(c->wbuf_len);
/* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR
...@@ -484,7 +487,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) ...@@ -484,7 +487,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
spin_lock(&c->erase_completion_lock); spin_lock(&c->erase_completion_lock);
/* Adjust free size of the block if we padded. */ /* Adjust free size of the block if we padded. */
if (pad && !jffs2_dataflash(c)) { if (pad) {
struct jffs2_eraseblock *jeb; struct jffs2_eraseblock *jeb;
jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
...@@ -601,15 +604,6 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c) ...@@ -601,15 +604,6 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c)
return ret; return ret;
} }
#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
#define PAGE_DIV(x) ( ((unsigned long)(x) / (unsigned long)(c->wbuf_pagesize)) * (unsigned long)(c->wbuf_pagesize) )
#define PAGE_MOD(x) ( (unsigned long)(x) % (unsigned long)(c->wbuf_pagesize) )
#else
#define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) )
#define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) )
#endif
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) 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)
{ {
struct kvec outvecs[3]; struct kvec outvecs[3];
...@@ -1203,14 +1197,38 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { ...@@ -1203,14 +1197,38 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
/* Initialize write buffer */ /* Initialize write buffer */
init_rwsem(&c->wbuf_sem); init_rwsem(&c->wbuf_sem);
c->wbuf_pagesize = c->sector_size;
c->wbuf_ofs = 0xFFFFFFFF;
c->wbuf_pagesize = c->mtd->erasesize;
/* Find a suitable c->sector_size
* - Not too much sectors
* - Sectors have to be at least 4 K + some bytes
* - All known dataflashes have erase sizes of 528 or 1056
* - we take at least 8 eraseblocks and want to have at least 8K size
* - The concatenation should be a power of 2
*/
c->sector_size = 8 * c->mtd->erasesize;
while (c->sector_size < 8192) {
c->sector_size *= 2;
}
/* It may be necessary to adjust the flash size */
c->flash_size = c->mtd->size;
if ((c->flash_size % c->sector_size) != 0) {
c->flash_size = (c->flash_size / c->sector_size) * c->sector_size;
printk(KERN_WARNING "JFFS2 flash size adjusted to %dKiB\n", c->flash_size);
};
c->wbuf_ofs = 0xFFFFFFFF;
c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
if (!c->wbuf) if (!c->wbuf)
return -ENOMEM; return -ENOMEM;
printk(KERN_INFO "JFFS2 write-buffering enabled (%i)\n", c->wbuf_pagesize); printk(KERN_INFO "JFFS2 write-buffering enabled buffer (%d) erasesize (%d)\n", c->wbuf_pagesize, c->sector_size);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment