mtd/fs/jffs2 wbuf.c,1.31,1.32
David Woodhouse
dwmw2 at infradead.org
Mon Jun 30 10:36:50 EDT 2003
Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv11465/fs/jffs2
Modified Files:
wbuf.c
Log Message:
Clean up NAND ECC switches -- do it once only during mount, fail if
there's an ECC type we don't grok, etc.
Index: wbuf.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/wbuf.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- wbuf.c 30 Jun 2003 10:58:58 -0000 1.31
+++ wbuf.c 30 Jun 2003 14:36:47 -0000 1.32
@@ -24,23 +24,6 @@
/* two seconds timeout for timed wbuf-flushing */
#define WBUF_FLUSH_TIMEOUT 2 * HZ
-#define JFFS2_OOB_ECCPOS0 0
-#define JFFS2_OOB_ECCPOS1 1
-#define JFFS2_OOB_ECCPOS2 2
-#define JFFS2_OOB_ECCPOS3 3
-#define JFFS2_OOB_ECCPOS4 6
-#define JFFS2_OOB_ECCPOS5 7
-
-#define NAND_JFFS2_OOB8_FSDAPOS 6
-#define NAND_JFFS2_OOB16_FSDAPOS 8
-#define NAND_JFFS2_OOB8_FSDALEN 2
-#define NAND_JFFS2_OOB16_FSDALEN 8
-
-struct nand_oobinfo jffs2_oobinfo = {
- useecc: 1,
- eccpos: {JFFS2_OOB_ECCPOS0, JFFS2_OOB_ECCPOS1, JFFS2_OOB_ECCPOS2, JFFS2_OOB_ECCPOS3, JFFS2_OOB_ECCPOS4, JFFS2_OOB_ECCPOS5}
-};
-
static inline void jffs2_refile_wbuf_blocks(struct jffs2_sb_info *c)
{
struct list_head *this, *next;
@@ -179,7 +162,7 @@
/* else jffs2_flash_writev has actually filled in the rest of the
buffer for us, and will deal with the node refs etc. later. */
- ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, &jffs2_oobinfo);
+ ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo);
if (ret || retlen != c->wbuf_pagesize) {
if (ret)
@@ -396,7 +379,7 @@
outvecs[splitvec].iov_len = split_ofs;
/* We did cross a page boundary, so we write some now */
- ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, &jffs2_oobinfo);
+ ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo);
if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) {
/* At this point we have no problem,
c->wbuf is empty.
@@ -469,7 +452,7 @@
/* Read flash */
if (!jffs2_can_mark_obsolete(c)) {
- ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, &jffs2_oobinfo);
+ ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo);
if ( (ret == -EIO) && (*retlen == len) ) {
printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n",
@@ -527,20 +510,10 @@
int ret = 0;
int i,len,cnt,page;
size_t retlen;
- int fsdata_pos,badblock_pos,oob_size;
+ int oob_size;
oob_size = c->mtd->oobsize;
- switch(c->mtd->ecctype) {
- case MTD_ECC_SW:
- fsdata_pos = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDAPOS : NAND_JFFS2_OOB16_FSDAPOS;
- badblock_pos = NAND_BADBLOCK_POS;
- break;
- default:
- D1(printk(KERN_WARNING "jffs2_write_oob_empty(): Invalid ECC type\n"));
- return -EINVAL;
- }
-
/* allocate a buffer for all oob data in this sector */
len = 4 * oob_size;
buf = kmalloc(len, GFP_KERNEL);
@@ -568,7 +541,7 @@
/* Special check for first two pages */
for (page = 0; page < 2 * oob_size; page += oob_size) {
/* Check for bad block marker */
- if (buf[page+badblock_pos] != 0xff) {
+ if (buf[page+c->badblock_pos] != 0xff) {
D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Bad or failed block at %08x\n",jeb->offset));
/* Return 2 for bad and 3 for failed block
bad goes to list_bad and failed to list_erase */
@@ -577,7 +550,7 @@
}
cnt = oob_size;
if (mode)
- cnt -= fsdata_pos;
+ cnt -= c->fsdata_pos;
for(i = 0; i < cnt ; i+=sizeof(unsigned short)) {
unsigned short dat = *(unsigned short *)(&buf[page+i]);
if(dat != 0xffff) {
@@ -617,23 +590,11 @@
unsigned char *p;
int ret, i, cnt, retval = 0;
size_t retlen, offset;
- int fsdata_pos, fsdata_len, oob_size, badblock_pos;
+ int oob_size;
offset = jeb->offset;
oob_size = c->mtd->oobsize;
- switch (c->mtd->ecctype) {
- case MTD_ECC_SW:
- fsdata_pos = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDAPOS : NAND_JFFS2_OOB16_FSDAPOS;
- fsdata_len = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDALEN : NAND_JFFS2_OOB16_FSDALEN;
- badblock_pos = NAND_BADBLOCK_POS;
- break;
- default:
- D1 (printk (KERN_WARNING "jffs2_write_nand_cleanmarker(): Invalid ECC type\n"));
- return -EINVAL;
- }
-
-
/* Loop through the physical blocks */
for (cnt = 0; cnt < (c->sector_size / c->mtd->erasesize); cnt++) {
/*
@@ -653,14 +614,14 @@
}
/* Check for bad block marker */
- if (buf[badblock_pos] != 0xff) {
+ if (buf[c->badblock_pos] != 0xff) {
D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Bad block at %08x\n", jeb->offset));
return 2;
}
/* Check for failure counter in the second page */
- if (buf[badblock_pos + oob_size] != 0xff) {
- D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Block marked as failed at %08x, fail count:%d\n", jeb->offset, buf[badblock_pos + oob_size]));
+ if (buf[c->badblock_pos + oob_size] != 0xff) {
+ D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Block marked as failed at %08x, fail count:%d\n", jeb->offset, buf[c->badblock_pos + oob_size]));
return 3;
}
@@ -671,8 +632,8 @@
n.totlen = cpu_to_je32 (8);
p = (unsigned char *) &n;
- for (i = 0; i < fsdata_len; i++) {
- if (buf[fsdata_pos + i] != p[i]) {
+ for (i = 0; i < c->fsdata_len; i++) {
+ if (buf[c->fsdata_pos + i] != p[i]) {
D2 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Cleanmarker node not detected in block at %08x\n", jeb->offset));
retval = 1;
}
@@ -687,31 +648,20 @@
{
struct jffs2_unknown_node n;
int ret;
- int fsdata_pos,fsdata_len;
size_t retlen;
- switch(c->mtd->ecctype) {
- case MTD_ECC_SW:
- fsdata_pos = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDAPOS : NAND_JFFS2_OOB16_FSDAPOS;
- fsdata_len = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDALEN : NAND_JFFS2_OOB16_FSDALEN;
- break;
- default:
- D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Invalid ECC type\n"));
- return -EINVAL;
- }
-
n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
n.totlen = cpu_to_je32(8);
- ret = jffs2_flash_write_oob(c, jeb->offset + fsdata_pos, fsdata_len, &retlen, (unsigned char *)&n);
+ ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n);
if (ret) {
D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret));
return ret;
}
- if (retlen != fsdata_len) {
- D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Short write for block at %08x: %zd not %d\n", jeb->offset, retlen, fsdata_len));
+ if (retlen != c->fsdata_len) {
+ D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Short write for block at %08x: %zd not %d\n", jeb->offset, retlen, c->fsdata_len));
return ret;
}
return 0;
@@ -725,18 +675,9 @@
unsigned char buf[16];
int ret;
size_t retlen;
- int oob_size, badblock_pos;
+ int oob_size;
oob_size = c->mtd->oobsize;
-
- switch(c->mtd->ecctype) {
- case MTD_ECC_SW:
- badblock_pos = NAND_BADBLOCK_POS;
- break;
- default:
- D1(printk(KERN_WARNING "jffs2_nand_read_failcnt(): Invalid ECC type\n"));
- return -EINVAL;
- }
ret = c->mtd->read_oob(c->mtd, jeb->offset + c->mtd->oobblock, oob_size , &retlen, buf);
@@ -750,7 +691,7 @@
return -EIO;
}
- jeb->bad_count = buf[badblock_pos];
+ jeb->bad_count = buf[c->badblock_pos];
return 0;
}
@@ -767,25 +708,16 @@
int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
{
unsigned char buf = 0x0;
- int ret,pos;
+ int ret;
size_t retlen;
- switch(c->mtd->ecctype) {
- case MTD_ECC_SW:
- pos = NAND_BADBLOCK_POS;
- break;
- default:
- D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Invalid ECC type\n"));
- return -EINVAL;
- }
-
/* if the count is < max, we try to write the counter to the 2nd page oob area */
if( ++jeb->bad_count < MAX_ERASE_FAILURES) {
buf = (unsigned char)jeb->bad_count;
- pos += c->mtd->oobblock;
+ c->badblock_pos += c->mtd->oobblock;
}
- ret = jffs2_flash_write_oob(c, jeb->offset + pos, 1, &retlen, &buf);
+ ret = jffs2_flash_write_oob(c, jeb->offset + c->badblock_pos, 1, &retlen, &buf);
if (ret) {
D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Write failed for block at %08x: error %d\n", jeb->offset, ret));
@@ -798,6 +730,25 @@
return 0;
}
+#define JFFS2_OOB_ECCPOS0 0
+#define JFFS2_OOB_ECCPOS1 1
+#define JFFS2_OOB_ECCPOS2 2
+#define JFFS2_OOB_ECCPOS3 3
+#define JFFS2_OOB_ECCPOS4 6
+#define JFFS2_OOB_ECCPOS5 7
+
+#define NAND_JFFS2_OOB8_FSDAPOS 6
+#define NAND_JFFS2_OOB16_FSDAPOS 8
+#define NAND_JFFS2_OOB8_FSDALEN 2
+#define NAND_JFFS2_OOB16_FSDALEN 8
+
+static struct nand_oobinfo jffs2_oobinfo_swecc = {
+ useecc: 1,
+ eccpos: {JFFS2_OOB_ECCPOS0, JFFS2_OOB_ECCPOS1, JFFS2_OOB_ECCPOS2, JFFS2_OOB_ECCPOS3, JFFS2_OOB_ECCPOS4, JFFS2_OOB_ECCPOS5}
+};
+
+
+
int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
{
/* Cleanmarker is out-of-band, so inline size zero */
@@ -806,9 +757,6 @@
/* Initialise write buffer */
c->wbuf_pagesize = c->mtd->oobblock;
c->wbuf_ofs = 0xFFFFFFFF;
- c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
- if (!c->wbuf)
- return -ENOMEM;
/* Initialise process for timed wbuf flush */
INIT_WORK(&c->wbuf_task,(void*) jffs2_wbuf_process, (void *)c);
@@ -817,6 +765,29 @@
init_timer(&c->wbuf_timer);
c->wbuf_timer.function = jffs2_wbuf_timeout;
c->wbuf_timer.data = (unsigned long) c;
+
+ switch(c->mtd->ecctype) {
+ case MTD_ECC_SW:
+ c->oobinfo = &jffs2_oobinfo_swecc;
+ if (c->mtd->oobsize == 8) {
+ c->fsdata_pos = NAND_JFFS2_OOB8_FSDAPOS;
+ c->fsdata_len = NAND_JFFS2_OOB8_FSDALEN;
+ } else {
+ c->fsdata_pos = NAND_JFFS2_OOB16_FSDAPOS;
+ c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN;
+ }
+ c->badblock_pos = NAND_BADBLOCK_POS;
+ break;
+
+ default:
+ printk("JFFS2 doesn't yet know how to handle ECC type %d\n",
+ c->mtd->ecctype);
+ return -EINVAL;
+ }
+
+ c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
+ if (!c->wbuf)
+ return -ENOMEM;
return 0;
}
More information about the linux-mtd-cvs
mailing list