changeset 300:4d9d442da93f

Allow the disabling of tags ECC
author charles <charles>
date Wed, 14 Oct 2009 00:01:56 +0000
parents acc06403a0bc
children 5563bf238683
files Kconfig direct/yaffs_fileem2k.c direct/yaffs_ramem2k.c moduleconfig.h yaffs_fs.c yaffs_guts.h yaffs_mtdif2.c yaffs_packedtags2.c yaffs_packedtags2.h
diffstat 9 files changed, 78 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/Kconfig
+++ b/Kconfig
@@ -90,6 +90,18 @@ config YAFFS_AUTO_YAFFS2
 
 	  If unsure, say Y.
 
+config YAFFS_DISABLE_TAGS_ECC
+	bool "Disable YAFFS from doing ECC on tags by default"
+	depends on YAFFS_FS && YAFFS_YAFFS2
+	default n
+	help
+	  This defaults Yaffs to using its own ECC calculations on tags instead of
+	  just relying on the MTD.
+	  This behavior can also be overridden with tags_ecc_on and
+	  tags_ecc_off mount options.
+
+	  If unsure, say N.
+
 config YAFFS_DISABLE_LAZY_LOAD
 	bool "Disable lazy loading"
 	depends on YAFFS_YAFFS2
--- a/direct/yaffs_fileem2k.c
+++ b/direct/yaffs_fileem2k.c
@@ -16,7 +16,7 @@
  * This is only intended as test code to test persistence etc.
  */
 
-const char *yaffs_flashif2_c_version = "$Id: yaffs_fileem2k.c,v 1.18 2009-01-16 02:26:56 charles Exp $";
+const char *yaffs_flashif2_c_version = "$Id: yaffs_fileem2k.c,v 1.19 2009-10-14 00:01:57 charles Exp $";
 
 
 #include "yportenv.h"
@@ -258,7 +258,7 @@ int yflash2_WriteChunkWithTagsToNAND(yaf
 			else
 			{
 				yaffs_PackedTags2 pt;
-				yaffs_PackTags2(&pt,tags);
+				yaffs_PackTags2(dev,&pt,tags);
 				__u8 * ptab = (__u8 *)&pt;
 
 				nRead = read(h,localBuffer,sizeof(pt));
@@ -336,7 +336,7 @@ int yflash2_WriteChunkWithTagsToNAND(yaf
 			else
 			{
 				yaffs_PackedTags2 pt;
-				yaffs_PackTags2(&pt,tags);
+				yaffs_PackTags2(dev,&pt,tags);
 				__u8 * ptab = (__u8 *)&pt;
 
 				nRead = read(h,localBuffer,sizeof(pt));
@@ -471,7 +471,7 @@ int yflash2_ReadChunkWithTagsFromNAND(ya
 			{
 				yaffs_PackedTags2 pt;
 				nread= read(h,&pt,sizeof(pt));
-				yaffs_UnpackTags2(tags,&pt);
+				yaffs_UnpackTags2(dev,tags,&pt);
 #ifdef SIMULATE_FAILURES
 				if((chunkInNAND >> 6) == 100) {
 					if(fail300 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
--- a/direct/yaffs_ramem2k.c
+++ b/direct/yaffs_ramem2k.c
@@ -16,7 +16,7 @@
  */
 
 
-const char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.4 2008-05-05 07:58:58 charles Exp $";
+const char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.5 2009-10-14 00:01:57 charles Exp $";
 
 #ifndef __KERNEL__
 #define CONFIG_YAFFS_RAM_ENABLED
@@ -220,7 +220,7 @@ int nandemul2k_WriteChunkWithTagsToNAND(
 	{
 		x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE];
 		
-		yaffs_PackTags2((yaffs_PackedTags2 *)x,tags);
+		yaffs_PackTags2(dev,(yaffs_PackedTags2 *)x,tags);
 			
 	}
 	
@@ -256,7 +256,7 @@ int nandemul2k_ReadChunkWithTagsFromNAND
 	{
 		x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE];
 		
-		yaffs_UnpackTags2(tags,(yaffs_PackedTags2 *)x);
+		yaffs_UnpackTags2(dev,tags,(yaffs_PackedTags2 *)x);
 	}
 
 	return YAFFS_OK;
--- a/moduleconfig.h
+++ b/moduleconfig.h
@@ -29,6 +29,10 @@
 /* Meaning: Yaffs does its own ECC, rather than using MTD ECC */
 /* #define CONFIG_YAFFS_DOES_ECC */
 
+/* Default: Selected */
+/* Meaning: Yaffs does its own ECC on tags for packed tags rather than use mtd */
+#define CONFIG_YAFFS_DOES_TAGS_ECC
+
 /* Default: Not selected */
 /* Meaning: ECC byte order is 'wrong'.  Only meaningful if */
 /*          CONFIG_YAFFS_DOES_ECC is set */
--- a/yaffs_fs.c
+++ b/yaffs_fs.c
@@ -32,7 +32,7 @@
  */
 
 const char *yaffs_fs_c_version =
-    "$Id: yaffs_fs.c,v 1.83 2009-09-23 23:24:55 charles Exp $";
+    "$Id: yaffs_fs.c,v 1.84 2009-10-14 00:01:56 charles Exp $";
 extern const char *yaffs_guts_c_version;
 
 #include <linux/version.h>
@@ -1812,6 +1812,8 @@ typedef struct {
 	int skip_checkpoint_read;
 	int skip_checkpoint_write;
 	int no_cache;
+	int tags_ecc_on;
+	int tags_ecc_overridden;
 } yaffs_options;
 
 #define MAX_OPT_LEN 20
@@ -1827,6 +1829,9 @@ static int yaffs_parse_options(yaffs_opt
 		memset(cur_opt, 0, MAX_OPT_LEN + 1);
 		p = 0;
 
+		while(*options_str == ',')
+			options_str++;
+
 		while (*options_str && *options_str != ',') {
 			if (p < MAX_OPT_LEN) {
 				cur_opt[p] = *options_str;
@@ -1837,7 +1842,13 @@ static int yaffs_parse_options(yaffs_opt
 
 		if (!strcmp(cur_opt, "inband-tags"))
 			options->inband_tags = 1;
-		else if (!strcmp(cur_opt, "no-cache"))
+		else if (!strcmp(cur_opt, "tags-ecc-off")){
+			options->tags_ecc_on = 0;
+			options->tags_ecc_overridden=1;
+		} else if (!strcmp(cur_opt, "tags-ecc-on")){
+			options->tags_ecc_on = 1;
+			options->tags_ecc_overridden = 1;
+		} else if (!strcmp(cur_opt, "no-cache"))
 			options->no_cache = 1;
 		else if (!strcmp(cur_opt, "no-checkpoint-read"))
 			options->skip_checkpoint_read = 1;
@@ -2053,6 +2064,12 @@ static struct super_block *yaffs_interna
 	dev->nShortOpCaches = (options.no_cache) ? 0 : 10;
 	dev->inbandTags = options.inband_tags;
 
+#ifdef CONFIG_YAFFS_DISABLE_TAGS_ECC
+	dev->noTagsECC = 1;
+#endif
+	if(options.tags_ecc_overridden)
+		dev->noTagsECC = !options.tags_ecc_on;
+
 	/* ... and the functions. */
 	if (yaffsVersion == 2) {
 		dev->writeChunkWithTagsToNAND =
@@ -2289,6 +2306,7 @@ static char *yaffs_dump_dev(char *buf, y
 	buf +=
 	    sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions);
 	buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC);
+	buf += sprintf(buf, "noTagsECC.......... %d\n", dev->noTagsECC);
 	buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2);
 	buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags);
 
--- a/yaffs_guts.h
+++ b/yaffs_guts.h
@@ -557,7 +557,8 @@ struct yaffs_DeviceStruct {
 
 	int useHeaderFileSize;	/* Flag to determine if we should use file sizes from the header */
 
-	int useNANDECC;		/* Flag to decide whether or not to use NANDECC */
+	int useNANDECC;		/* Flag to decide whether or not to use NANDECC on data (yaffs1) */
+	int noTagsECC;		/* Flag to decide whether or not to do ECC on packed tags (yaffs2) */ 
 
 	void *genericDevice;	/* Pointer to device context
 				 * On an mtd this holds the mtd pointer.
--- a/yaffs_mtdif2.c
+++ b/yaffs_mtdif2.c
@@ -14,7 +14,7 @@
 /* mtd interface for YAFFS2 */
 
 const char *yaffs_mtdif2_c_version =
-	"$Id: yaffs_mtdif2.c,v 1.23 2009-03-06 17:20:53 wookey Exp $";
+	"$Id: yaffs_mtdif2.c,v 1.24 2009-10-14 00:01:57 charles Exp $";
 
 #include "yportenv.h"
 
@@ -47,6 +47,9 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya
 
 	yaffs_PackedTags2 pt;
 
+	int packed_tags_size = dev->noTagsECC ? sizeof(pt.t) : sizeof(pt);
+	void * packed_tags_ptr = dev->noTagsECC ? (void *) &pt.t : (void *)&pt;
+
 	T(YAFFS_TRACE_MTD,
 	  (TSTR
 	   ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
@@ -66,22 +69,22 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya
 		pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
 		yaffs_PackTags2TagsPart(pt2tp, tags);
 	} else
-		yaffs_PackTags2(&pt, tags);
+		yaffs_PackTags2(dev, &pt, tags);
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
 	ops.mode = MTD_OOB_AUTO;
-	ops.ooblen = (dev->inbandTags) ? 0 : sizeof(pt);
+	ops.ooblen = (dev->inbandTags) ? 0 : packed_tags_size;
 	ops.len = dev->totalBytesPerChunk;
 	ops.ooboffs = 0;
 	ops.datbuf = (__u8 *)data;
-	ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt;
+	ops.oobbuf = (dev->inbandTags) ? NULL : packed_tags_ptr;
 	retval = mtd->write_oob(mtd, addr, &ops);
 
 #else
 	if (!dev->inbandTags) {
 		retval =
 		    mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
-				   &dummy, data, (__u8 *) &pt, NULL);
+				   &dummy, data, (__u8 *) packed_tags_ptr, NULL);
 	} else {
 		retval =
 		    mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy,
@@ -110,6 +113,9 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
 
 	yaffs_PackedTags2 pt;
 
+	int packed_tags_size = dev->noTagsECC ? sizeof(pt.t) : sizeof(pt);
+	void * packed_tags_ptr = dev->noTagsECC ? (void *) &pt.t: (void *)&pt;
+
 	T(YAFFS_TRACE_MTD,
 	  (TSTR
 	   ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
@@ -132,8 +138,8 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
 				&dummy, data);
 	else if (tags) {
 		ops.mode = MTD_OOB_AUTO;
-		ops.ooblen = sizeof(pt);
-		ops.len = data ? dev->nDataBytesPerChunk : sizeof(pt);
+		ops.ooblen = packed_tags_size;
+		ops.len = data ? dev->nDataBytesPerChunk : packed_tags_size;
 		ops.ooboffs = 0;
 		ops.datbuf = data;
 		ops.oobbuf = dev->spareBuffer;
@@ -166,8 +172,8 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
 		}
 	} else {
 		if (tags) {
-			memcpy(&pt, dev->spareBuffer, sizeof(pt));
-			yaffs_UnpackTags2(tags, &pt);
+			memcpy(packed_tags_ptr, dev->spareBuffer, packed_tags_size);
+			yaffs_UnpackTags2(dev, tags, &pt);
 		}
 	}
 
--- a/yaffs_packedtags2.c
+++ b/yaffs_packedtags2.c
@@ -96,17 +96,14 @@ void yaffs_PackTags2TagsPart(yaffs_Packe
 }
 
 
-void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t)
+void yaffs_PackTags2(yaffs_Device *dev, yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t)
 {
 	yaffs_PackTags2TagsPart(&pt->t, t);
 
-#ifndef YAFFS_IGNORE_TAGS_ECC
-	{
+	if(!dev->noTagsECC)
 		yaffs_ECCCalculateOther((unsigned char *)&pt->t,
 					sizeof(yaffs_PackedTags2TagsPart),
 					&pt->ecc);
-	}
-#endif
 }
 
 
@@ -158,27 +155,24 @@ void yaffs_UnpackTags2TagsPart(yaffs_Ext
 }
 
 
-void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt)
+void yaffs_UnpackTags2(yaffs_Device *dev, yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt)
 {
 
 	yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR;
 
-	if (pt->t.sequenceNumber != 0xFFFFFFFF) {
-		/* Page is in use */
-#ifndef YAFFS_IGNORE_TAGS_ECC
-		{
-			yaffs_ECCOther ecc;
-			int result;
-			yaffs_ECCCalculateOther((unsigned char *)&pt->t,
-						sizeof
-						(yaffs_PackedTags2TagsPart),
-						&ecc);
-			result =
-			    yaffs_ECCCorrectOther((unsigned char *)&pt->t,
-						  sizeof
-						  (yaffs_PackedTags2TagsPart),
-						  &pt->ecc, &ecc);
-			switch (result) {
+	if (pt->t.sequenceNumber != 0xFFFFFFFF &&
+	    !dev->noTagsECC){
+		/* Chunk is in use and we need to do ECC */
+		
+		yaffs_ECCOther ecc;
+		int result;
+		yaffs_ECCCalculateOther((unsigned char *)&pt->t,
+					sizeof(yaffs_PackedTags2TagsPart),
+					&ecc);
+		result = yaffs_ECCCorrectOther((unsigned char *)&pt->t,
+						sizeof(yaffs_PackedTags2TagsPart),
+						&pt->ecc, &ecc);
+		switch (result) {
 			case 0:
 				eccResult = YAFFS_ECC_RESULT_NO_ERROR;
 				break;
@@ -190,9 +184,7 @@ void yaffs_UnpackTags2(yaffs_ExtendedTag
 				break;
 			default:
 				eccResult = YAFFS_ECC_RESULT_UNKNOWN;
-			}
 		}
-#endif
 	}
 
 	yaffs_UnpackTags2TagsPart(t, &pt->t);
@@ -201,6 +193,5 @@ void yaffs_UnpackTags2(yaffs_ExtendedTag
 
 	yaffs_DumpPackedTags2(pt);
 	yaffs_DumpTags2(t);
-
 }
 
--- a/yaffs_packedtags2.h
+++ b/yaffs_packedtags2.h
@@ -34,8 +34,8 @@ typedef struct {
 } yaffs_PackedTags2;
 
 /* Full packed tags with ECC, used for oob tags */
-void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t);
-void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt);
+void yaffs_PackTags2(yaffs_Device *dev, yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t);
+void yaffs_UnpackTags2(yaffs_Device *dev, yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt);
 
 /* Only the tags part (no ECC for use with inband tags */
 void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *pt, const yaffs_ExtendedTags *t);