[Yaffs-archive] Re: Latest CVS

Thomas Gleixner tglx@linutronix.de
Sun, 24 Nov 2002 22:24:19 +0100


--Boundary_(ID_+Dumof/A01Dt+CawZq3jbg)
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: 7BIT

On Sunday 24 November 2002 20:00, Nick Bane wrote:
> Well I might offer one more instance - and that relates to yaffs too. That
> is when the fs uses other parts of the oob data and is running on chips
> that only accept two writes to the oob area. Under those circumstances we
> want the fs and not the mtd layer to do the writing assuming that a second
> write to the oob is part of the fs's bad block strategy.
If I understand YAFFS correctly, then the OOB data are written in one go 
together with data. So the fs supplies all oob data except ECC and the driver 
fills in either SW or HW generated ECC at the appropriate place for the 
calling fs. So fs supplied OOB data and ECC are written in one cycle. It's 
not a two step procedure.

> Also, if I am being picky, I believe that hardware assisted ecc can be
> implemented where the hardware just does the arithmetic. It is then up to
> the driver to read that data and write it out to the oob. If it *really*
> wanted to, an fs could ignore the results and write something else. This
> would make it reasonable for fs's on different partitions to use/ignore the
> Hardware ECC.
Yep, but I assume, that somebody, who has HW ECC is willing to use it. And all 
NAND aware filesystems will use ECC.

I was curious and modified YAFFS to use nand ecc. It works. The modifications 
are really small. I copied files around with nandecc enabled and verified it 
afterwards with nandecc disabled. Enable/disable is in YAFFS only, not in 
nand.c, where NAND_SW_ECC is selected for the hole chip, as I have a JFFS2 
root partition on the same chip. This runs on top of current MTD-CVS without 
any modification. The NAND driver HW-ECC support is therefore available for 
YAFFS out of the box.

A penalty is that I have to copy oob data around on read, because NAND driver  
returns 16Byte OOB data and 2 x 4 Byte ECC correction result. This was a 
request of Charles, when we discussed some YAFFS issues before I did the big 
nand.c overhaul. This behaviour is a subject, which could be changed, as the 
only user would be YAFFS at the moment, AFAIK. 

A further improvement would be to use the NAND driver write verify function 
and skip this function in YAFFS. Therefor the return value from 
mtd->write_ecc has to be evaluated inside YAFFS. This would be recommended, 
if you intend to use JFFS2 and YAFFS together and want to have the write 
verify for both filesystems. At the moment a double checking is done for 
YAFFS, if it is enabled in the nand driver. JFFS2 does not support write 
verify in the fs layer. It relies on the write verify of the nand driver and 
handles the results.

Patch attached.
Jeffrey: Forgive me, that I did not change the if statements. I was to lazy :)

I have added a section about this issue to 
http://www.linux-mtd.infradead.org/tech/nand.html.

-- 
Thomas
____________________________________________________
linutronix - competence in embedded & realtime linux
http://www.linutronix.de
mail: tglx@linutronix.de

--Boundary_(ID_+Dumof/A01Dt+CawZq3jbg)
Content-type: text/x-diff; charset=iso-8859-1; name=yaffs.diff
Content-transfer-encoding: 7BIT
Content-disposition: attachment; filename=yaffs.diff

? cvs.diff
Index: Makefile
===================================================================
RCS file: /home/aleph1/cvs/yaffs/Makefile,v
retrieving revision 1.5
diff -u -r1.5 Makefile
--- Makefile	27 Aug 2002 03:31:38 -0000	1.5
+++ Makefile	24 Nov 2002 18:53:27 -0000
@@ -15,7 +15,7 @@
 ## Change or override  KERNELDIR to your kernel
 ## comment out USE_xxxx if you don't want these features.
 
-KERNELDIR = /usr/src/kernel-headers-2.4.18
+KERNELDIR = /home/thomas/work/linux
 
 # Configurations...
 # Comment out the stuff you don't want.
@@ -25,7 +25,7 @@
 # This adds the yaffsram file system support. Nice for testing on x86, but uses 2MB of RAM.
 # Don't enable for NAND-based targets.
 
-USE_RAM_FOR_TEST = -DCONFIG_YAFFS_RAM_ENABLED
+#USE_RAM_FOR_TEST = -DCONFIG_YAFFS_RAM_ENABLED
 
 
 # CONFIG_YAFFS_MTD_ENABLED.
@@ -33,6 +33,11 @@
 
 USE_MTD = -DCONFIG_YAFFS_MTD_ENABLED
 
+# CONFIG_YAFFS_USE_NANDECC.
+# This enables the ECC functions of the generic MTD-NAND driver
+
+USE_NANDECC = -DCONFIG_YAFFS_USE_NANDECC
+
 # CONFIG_YAFFS_USE_GENERIC_RW
 # Use generic_read/generic_write for reading/writing files. This enables the use of the Linux
 # file caching layer.
@@ -55,7 +60,7 @@
 # this is safe, since the write verification will fail.
 # Suggest enabling the test (ie. keep the following line commented) during development to help debug things.
 
-#IGNORE_CHUNK_ERASED = -DCONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK
+IGNORE_CHUNK_ERASED = -DCONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK
 
 #CONFIG_YAFFS_DISABLE_WRITE_VERIFY
 # I am severely reluctant to provide this config. Disabling the verification is not a good thing to do
@@ -67,7 +72,7 @@
 
 # End of configuration options.
 
-YAFFS_CONFIGS = $(USE_RAM_FOR_TEST) $(USE_MTD) $(USE_GENERIC_RW) $(USE_HEADER_FILE_SIZE) $(IGNORE_CHUNK_ERASED) $(IGNORE_WRITE_VERIFY)
+YAFFS_CONFIGS = $(USE_RAM_FOR_TEST) $(USE_MTD) $(USE_GENERIC_RW) $(USE_HEADER_FILE_SIZE) $(IGNORE_CHUNK_ERASED) $(IGNORE_WRITE_VERIFY) $(USE_NANDECC)
 
 CFLAGS = -D__KERNEL__ -DMODULE $(YAFFS_CONFIGS)  -I$(KERNELDIR)/include -O2 -Wall
 
@@ -78,10 +83,10 @@
 all: yaffs.o
 
 $(OBJS): %.o: %.c Makefile
-	gcc -c $(CFLAGS) $< -o $@
+	arm-linux-gcc -c $(CFLAGS) $< -o $@
 
 yaffs.o: $(OBJS)
-	ld -r $(OBJS) -o $@
+	arm-linux-ld -r $(OBJS) -o $@
 
 clean:
 	rm -f $(OBJS) core
Index: yaffs_guts.c
===================================================================
RCS file: /home/aleph1/cvs/yaffs/yaffs_guts.c,v
retrieving revision 1.7
diff -u -r1.7 yaffs_guts.c
--- yaffs_guts.c	27 Aug 2002 03:31:38 -0000	1.7
+++ yaffs_guts.c	24 Nov 2002 18:53:32 -0000
@@ -131,14 +131,22 @@
 	return dev->writeChunkToNAND(dev,chunkInNAND,data,spare);
 }
 
+struct nandspare {
+	yaffs_Spare	spare;
+	int		eccres1;
+	int		eccres2;
+};
 
 int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare,int doErrorCorrection)
 {
 	int retVal;
-	__u8 calcEcc[3];
 	yaffs_Spare localSpare;
+#ifndef CONFIG_YAFFS_USE_NANDECC
+	__u8 calcEcc[3];
 	int eccResult1,eccResult2;
-	
+#else
+	struct nandspare nspare;
+#endif	
 	dev->nPageReads++;
 	
 	if(!spare && data)
@@ -148,6 +156,8 @@
 		spare = &localSpare;
 	}
 	
+
+#ifndef CONFIG_YAFFS_USE_NANDECC
 	retVal  = dev->readChunkFromNAND(dev,chunkInNAND,data,spare);
 	if(data && doErrorCorrection)
 	{
@@ -181,7 +191,38 @@
 		 	// Hoosterman, we had a data problem on this page
 			yaffs_HandleReadDataError(dev,chunkInNAND);
 		 }
-	}
+	}
+#else
+	retVal  = dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare*)&nspare);
+	memcpy (spare, &nspare, sizeof(yaffs_Spare));
+	if(data && doErrorCorrection)
+	{
+		 if(nspare.eccres1>0)
+		 {
+		 	T((TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND));
+		 }
+		 else if(nspare.eccres1<0)
+		 {
+		 	T((TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND));
+		 }
+		 
+		 if(nspare.eccres2>0)
+		 {
+		 	T((TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND));
+		 }
+		 else if(nspare.eccres2<0)
+		 {
+		 	T((TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND));
+		 }
+		 
+		 if(nspare.eccres2 || nspare.eccres2)
+		 {
+		 	// Hoosterman, we had a data problem on this page
+			yaffs_HandleReadDataError(dev,chunkInNAND);
+		 }
+	
+	}	
+#endif
 	return retVal;
 }
 
@@ -1956,11 +1997,12 @@
 	yaffs_SpareInitialise(&spare);
 	
 
+#ifndef CONFIG_YAFFS_USE_NANDECC	
 	if(buffer)
 	{
 		yaffs_CalcECC(buffer,&spare);
 	}
-	
+#endif	
 	yaffs_LoadTagsIntoSpare(&spare,tags);
 	
 	return yaffs_WriteChunkToNAND(dev,chunkInNAND,buffer,&spare);
@@ -1984,11 +2026,12 @@
 	yaffs_SpareInitialise(&spare);
 	
 
+#ifndef CONFIG_YAFFS_USE_NANDECC	
 	if(buffer)
 	{
 		yaffs_CalcECC(buffer,&spare);
 	}
-	
+#endif	
 	yaffs_LoadTagsIntoSpare(&spare,tags);
 	
 	return yaffs_WriteNewChunkToNAND(dev,buffer,&spare,useReserve);
@@ -3731,10 +3774,10 @@
 
 /////////////////// YAFFS test code //////////////////////////////////
 
-#define yaffs_CheckStruct(structure,syze, name) \
-           if(sizeof(structure) != syze) \
-	       { YPRINTF(("%s should be %d but is %d\n",name,syze,sizeof(structure))); \
-	         return YAFFS_FAIL; \
+#define yaffs_CheckStruct(structure,syze, name) \
+	if(sizeof(structure) != syze) \
+	       { YPRINTF(("%s should be %d but is %d\n",name,syze,sizeof(structure))); \
+	         return YAFFS_FAIL; \
 		   }
 		 
 		 
Index: yaffs_mtdif.c
===================================================================
RCS file: /home/aleph1/cvs/yaffs/yaffs_mtdif.c,v
retrieving revision 1.2
diff -u -r1.2 yaffs_mtdif.c
--- yaffs_mtdif.c	27 Aug 2002 03:31:38 -0000	1.2
+++ yaffs_mtdif.c	24 Nov 2002 18:53:33 -0000
@@ -20,7 +20,7 @@
 
 #include "linux/mtd/mtd.h"
 #include "linux/types.h"
-
+#include "linux/mtd/nand.h"
 
 int nandmtd_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_Spare *spare)
 {
@@ -32,11 +32,16 @@
 	
 	__u8 *spareAsBytes = (__u8 *)spare;
 	
-	if(data)
+	if(data && !spare)
 		mtd->write(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data);
-	if(spare)
+	if(!data && spare)
 		mtd->write_oob(mtd,addr,YAFFS_BYTES_PER_SPARE,&dummy,spareAsBytes);
-
+	if(data && spare)
+#ifdef CONFIG_YAFFS_USE_NANDECC		
+		mtd->write_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_YAFFS_OOB);
+#else
+		mtd->write_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_NONE_OOB);
+#endif
 	return YAFFS_OK;
 }
 
@@ -50,10 +55,16 @@
 	
 	__u8 *spareAsBytes = (__u8 *)spare;
 	
-	if(data)
+	if(data && !spare)
 		mtd->read(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data);
-	if(spare)
+	if(!data && spare)
 		mtd->read_oob(mtd,addr,YAFFS_BYTES_PER_SPARE,&dummy,spareAsBytes);
+	if(data && spare)
+#ifdef CONFIG_YAFFS_USE_NANDECC		
+		mtd->read_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_YAFFS_OOB);
+#else
+		mtd->read_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_NONE_OOB);
+#endif
 
 	return YAFFS_OK;
 }

--Boundary_(ID_+Dumof/A01Dt+CawZq3jbg)--


---------------------------------------------------------------------------------------
This mailing list is hosted by Toby Churchill open software (www.toby-churchill.org).
If mailing list membership is no longer wanted you can remove yourself from the list by 
sending an email to yaffs-request@toby-churchill.org with the text "unsubscribe" 
(without the quotes) as the subject.