# HG changeset patch # User charles # Date 1255478517 -3600 # Node ID 5d34d18f33e5f6a55768a148b5bdddb706020a1a # Parent 1206ae06f03d49914e423c96238d5d6fd8e38ed5 Allow the disabling of tags ECC diff --git a/Kconfig b/Kconfig --- 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 diff --git a/direct/yaffs_fileem2k.c b/direct/yaffs_fileem2k.c --- a/direct/yaffs_fileem2k.c +++ b/direct/yaffs_fileem2k.c @@ -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){ diff --git a/direct/yaffs_ramem2k.c b/direct/yaffs_ramem2k.c --- a/direct/yaffs_ramem2k.c +++ b/direct/yaffs_ramem2k.c @@ -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; diff --git a/moduleconfig.h b/moduleconfig.h --- 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 */ diff --git a/yaffs_fs.c b/yaffs_fs.c --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -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); diff --git a/yaffs_guts.h b/yaffs_guts.h --- 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. diff --git a/yaffs_mtdif2.c b/yaffs_mtdif2.c --- a/yaffs_mtdif2.c +++ b/yaffs_mtdif2.c @@ -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); } } diff --git a/yaffs_packedtags2.c b/yaffs_packedtags2.c --- 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); - } diff --git a/yaffs_packedtags2.h b/yaffs_packedtags2.h --- 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);