Re: EBH with OneNAND doesn't work

Christian Lehne
2005-12-19T10:58:03Z

Jarkko Lavinen wrote:
> I am trying to use JFFS2 (JFFS2 from cvs -D 'Nov 12, 2005' with the
> mtd driver part from CVS head) on OneNAND simulator and real OneNAND
> device.
>
> I erased the test partition with "flash_eraseall /dev/mtd0". I mount the
> partition and no other fs operation is done. When I just unmount and
mount
> again, I get
>
> # mount -t jffs2 /dev/mtdblock0 /mnt
> ...
> Dec 16 12:35:11 slayer kernel: jffs2_scan_eraseblock(): Scanning
block at 0x0
> Dec 16 12:35:11 slayer kernel: JFFS2: Erase block at 0x00000000 is
not formatted. It will be erased
> Dec 16 12:35:11 slayer kernel: jffs2_scan_eraseblock(): Scanning
block at 0x10000
> Dec 16 12:35:11 slayer kernel: JFFS2: Erase block at 0x00010000 is
not formatted. It will be erased
> ...
> Dec 16 12:35:11 slayer kernel: Cowardly refusing to erase blocks on
filesystem with no valid JFFS2 nodes
> Dec 16 12:35:11 slayer kernel: empty_blocks 0, bad_blocks 0,
c->nr_blocks 256
> Dec 16 12:35:11 slayer kernel: c->used_size: 0
> Dec 16 12:35:11 slayer kernel: c->nr_free_blocks 0
> Dec 16 12:35:11 slayer kernel:
(c->nr_free_blocks+empty_blocks+bad_blocks): 0
> Dec 16 12:35:11 slayer kernel: [JFFS2 DBG] (3779)
jffs2_do_mount_fs: build_fs failed
>
>
> JFFS2 is complaining about many pages being unformatted. It shouldn't
> do this, since the pages should be properly formatted after the first
> mount within a second when using a fast machine. At least on Nandsim and
> Ramtd they are.
>
> Also, no pages are used so pages shold be either free or empty but the
> number of free or empty pages is zero. This triggers the Cowardly
> message,
>
> I am seeing the same problem on both real OneNAND and OneNand
> simulator. On Nandsim or Ramtd everything seems to work ok.
>
> The problem might be related to the free OOB bytes being scattered in
> OneNand. The first free OOB region start at offset 2 and with length 3
> bytes with autoplacement.

Hi,

as my colleague announced we had the same problem with a
OneNAND512(KFG1216x2A) Chip.
We had two problems: the one with the oob-handling which is discussed in
another thread and the low-level read/write routine for onenand
So here are two patches which will work for us but which is
unfortunately not generic.

In onenand_base.c I changed the bitmask for oobfree. as i can see with
our chip i am not allowed to use (2,3) (reserved for crc), thats why i
toggled (14,2) (which is free) and (2,3).
the main problem i had is in
onenand_read_bufferram/onenand_write_bufferram.
as i understand bufferram-hardware accesses, i am not allowed to use
memcpy for this, instead i use a (slow!!) copy routine with
onenand_readw/onenand_writew. with that it works fine.
(interestingly i only got read/write errors in OOB-Area not in data-Area
when using memcpy.)

Note that i am working with 16Bit data. onenand_write_bufferram() will
fail if someone wrote an odd number of data!!!
can someone tell me if there are cases where this function is called
with an odd number of data?
in my target i can't see this.

In flash_eraseall.c there is a JFFS2_NODETYPE_ERASEBLOCK_HEADER-marker
written but i couldn't find such a marker in the kernel-sources, so i
replaced it with a cleanmarker which worked fine by us. but i miss the
whole to understand the effects of this, so maybe someone with more
experience can have a lock at this.
Also the size of the structures (jffs2_raw_ebh) in flash_eraseall and
kernel seems to differ, so we just use 8 Bytes instead.
Last we wrote only ebhlen Data to OOB-Area (ebhlen with our chip is 2
Bytes so we finally use only 2 bytes for OOB-Data, don't know if this is
enough but it works fine, think we will have to wait for a generic
solution with oob-handling)

sorry for my poor solution but i am currently under pressure of time (as
probably all of you.. ).

Regards,
Christian

diff -uN util/flash_eraseall.c a/util/flash_eraseall.c
--- util/flash_eraseall.c 2005-12-19 10:38:20.000000000 +0100
+++ util/flash_eraseall.c 2005-11-08 02:02:20.000000000 +0100
@@ -83,8 +83,8 @@

if (jffs2) {
ebh.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
+ ebh.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
+ ebh.totlen = cpu_to_je32(8);
- ebh.nodetype = cpu_to_je16
(JFFS2_NODETYPE_ERASEBLOCK_HEADER);
- ebh.totlen = cpu_to_je32(sizeof(struct jffs2_raw_ebh));
ebh.hdr_crc = cpu_to_je32 (crc32 (0, &ebh, sizeof
(struct jffs2_unknown_node) - 4));
ebh.reserved = 0;
ebh.compat_fset = JFFS2_EBH_COMPAT_FSET;
@@ -92,7 +92,7 @@
ebh.rocompat_fset = JFFS2_EBH_ROCOMPAT_FSET;
ebh.erase_count = cpu_to_je32(0);
ebh.node_crc = cpu_to_je32(crc32(0, (unsigned char
*)&ebh + sizeof(struct jffs2_unknown_node) + 4,
+ 8 - sizeof(struct
jffs2_unknown_node) - 4));
- sizeof(struct jffs2_raw_ebh) -
sizeof(struct jffs2_unknown_node) - 4));

if (isNAND) {
struct nand_oobinfo oobinfo;
@@ -182,11 +182,10 @@
struct mtd_oob_buf oob;
uint32_t i = 0, written = 0;

+ while (written < ebhlen) {
- while (written < sizeof(struct jffs2_raw_ebh)) {
oob.ptr = (unsigned char *) &ebh + written;
oob.start = erase.start +
meminfo.oobblock*i + ebhpos;
oob.length = (sizeof(struct
jffs2_raw_ebh) - written) < ebhlen ? (sizeof(struct jffs2_raw_ebh) -
written) : ebhlen;
+
if (ioctl (fd, MEMWRITEOOB, &oob) != 0) {
fprintf(stderr, "\n%s: %s: MTD
writeoob failure: %s\n", exe_name, mtd_device, strerror(errno));
break;

diff -uN ..
--- linux/drivers/mtd/onenand/onenand_base.c 2005-12-19
10:46:37.000000000 +0100
+++ linux/drivers/mtd/onenand/onenand_base.c 2005-12-16
02:02:11.000000000 +0100
@@ -33,8 +33,8 @@
56, 57, 58, 59, 60,
},
.oobfree = {
+ {14, 2}, { 2, 3}, {18, 3}, {30, 2},
+ {34, 3}, {46, 2}, {50, 3}, {62, 2} }
- {2, 3}, {14, 2}, {18, 3}, {30, 2},
- {24, 3}, {46, 2}, {40, 3}, {62, 2} }
};

/**
@@ -367,33 +367,12 @@
{
struct onenand_chip *this = mtd->priv;
void __iomem *bufferram;
+ unsigned short *p;
+ int i;

bufferram = this->base + area;

bufferram += onenand_bufferram_offset(mtd, area);

+ p = (unsigned short *)buffer;
+ for (i=0; i< (count >> 1 ); i++)
+ p[i] = onenand_readw(bufferram + offset + 2*i);
+ if(count%2)
+ buffer[count-1] = (unsigned char) (0xff &
onenand_readw(bufferram + offset + count - 1));
+
- memcpy(buffer, bufferram + offset, count);

return 0;
}
@@ -442,40 +421,12 @@
{
struct onenand_chip *this = mtd->priv;
void __iomem *bufferram;
+ unsigned short *p;
+ int i;

bufferram = this->base + area;

bufferram += onenand_bufferram_offset(mtd, area);

+ p = (unsigned short *)buffer;
+ for (i=0; i< (count >> 1 ); i++){
+ onenand_writew(*p, bufferram + offset + 2 * i);
+ p++;
+ }
+ if(count%2)
+ printk("FATAL ERROR: onenand_write_bufferram count is
odd : %x\n", count);
+ if(offset%2)
+ printk("FATAL ERROR: onenand_write_bufferram offset is
odd : %x\n", offset);
+
- memcpy(bufferram + offset, buffer, count);

return 0;
}