From 3321ac060648a65e47093e6f3e7387b4b1c5d5cd Mon Sep 17 00:00:00 2001 From: vwool Date: Tue, 26 Sep 2006 13:28:13 +0000 Subject: [PATCH] Interworking with 2.6.18 kernel enabled Notable is that to enable it for yaffs1 compatibility mode, I introduced a workaround (translate_spare2oob/translate_oob2spare) which should be redesigned if possible. The thing is that yaffs1 presumes SmartMedia OOB layout which might be not true for a lot of modern flash controllers, so there has to be translation. Or, in case we get to tags inband, this workaround will become useless. --- yaffs_fs.c | 101 +++++++++++++++++++++++++++++++++++++++++++++---- yaffs_mtdif.c | 92 ++++++++++++++++++++++++++++++++++++++++++-- yaffs_mtdif2.c | 42 +++++++++++++++++++- 3 files changed, 223 insertions(+), 12 deletions(-) diff --git a/yaffs_fs.c b/yaffs_fs.c index d90e291..30ac265 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -31,7 +31,7 @@ */ const char *yaffs_fs_c_version = - "$Id: yaffs_fs.c,v 1.51 2006-07-25 21:03:22 charles Exp $"; + "$Id: yaffs_fs.c,v 1.52 2006-09-26 13:28:13 vwool Exp $"; extern const char *yaffs_guts_c_version; #include @@ -103,7 +103,11 @@ static void yaffs_put_super(struct super_block *sb); static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_t * pos); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +static int yaffs_file_flush(struct file *file, fl_owner_t id); +#else static int yaffs_file_flush(struct file *file); +#endif static int yaffs_sync_object(struct file *file, struct dentry *dentry, int datasync); @@ -137,10 +141,17 @@ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry); static int yaffs_setattr(struct dentry *dentry, struct iattr *attr); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +static int yaffs_sync_fs(struct super_block *sb, int wait); +static void yaffs_write_super(struct super_block *sb); +#else static int yaffs_sync_fs(struct super_block *sb); static int yaffs_write_super(struct super_block *sb); +#endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf); +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf); #else static int yaffs_statfs(struct super_block *sb, struct statfs *buf); @@ -438,7 +449,11 @@ static void yaffs_delete_inode(struct inode *inode) clear_inode(inode); } +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +static int yaffs_file_flush(struct file *file, fl_owner_t id) +#else static int yaffs_file_flush(struct file *file) +#endif { yaffs_Object *obj = yaffs_DentryToObject(file->f_dentry); @@ -1257,14 +1272,21 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr) return error; } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev; + struct super_block *sb = dentry->d_sb; +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf) +{ + yaffs_Device *dev = yaffs_SuperToDevice(sb); #else static int yaffs_statfs(struct super_block *sb, struct statfs *buf) -#endif { - yaffs_Device *dev = yaffs_SuperToDevice(sb); +#endif + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_statfs\n")); yaffs_GrossLock(dev); @@ -1321,16 +1343,25 @@ static int yaffs_do_sync_fs(struct super_block *sb) } +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +static void yaffs_write_super(struct super_block *sb) +#else static int yaffs_write_super(struct super_block *sb) +#endif { T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n")); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) return 0; /* yaffs_do_sync_fs(sb);*/ - +#endif } +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +static int yaffs_sync_fs(struct super_block *sb, int wait) +#else static int yaffs_sync_fs(struct super_block *sb) +#endif { T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n")); @@ -1486,7 +1517,11 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, T(YAFFS_TRACE_OS, (" writeoob %p\n", mtd->write_oob)); T(YAFFS_TRACE_OS, (" block_isbad %p\n", mtd->block_isbad)); T(YAFFS_TRACE_OS, (" block_markbad %p\n", mtd->block_markbad)); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + T(YAFFS_TRACE_OS, (" writesize %d\n", mtd->writesize)); +#else T(YAFFS_TRACE_OS, (" oobblock %d\n", mtd->oobblock)); +#endif T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize)); T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize)); T(YAFFS_TRACE_OS, (" size %d\n", mtd->size)); @@ -1494,14 +1529,22 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, #ifdef CONFIG_YAFFS_AUTO_YAFFS2 if (yaffsVersion == 1 && +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + mtd->writesize >= 2048) { +#else mtd->oobblock >= 2048) { +#endif T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n")); yaffsVersion = 2; } /* Added NCB 26/5/2006 for completeness */ if (yaffsVersion == 2 && - mtd->oobblock == 512) { +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + mtd->writesize == 512) { +#else + mtd->oobblock >= 512) { +#endif T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n")); yaffsVersion = 1; } @@ -1515,15 +1558,23 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, !mtd->block_markbad || !mtd->read || !mtd->write || +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + !mtd->read_oob || !mtd->write_oob) { +#else !mtd->write_ecc || !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) { +#endif T(YAFFS_TRACE_ALWAYS, ("yaffs: MTD device does not support required " "functions\n"));; return NULL; } +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE || +#else if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE || +#endif mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) { T(YAFFS_TRACE_ALWAYS, ("yaffs: MTD device does not have the " @@ -1535,15 +1586,23 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, if (!mtd->erase || !mtd->read || !mtd->write || +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + !mtd->read_oob || !mtd->write_oob) { +#else !mtd->write_ecc || !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) { +#endif T(YAFFS_TRACE_ALWAYS, ("yaffs: MTD device does not support required " "functions\n"));; return NULL; } - if (mtd->oobblock != YAFFS_BYTES_PER_CHUNK || +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + if (mtd->writesize < YAFFS_BYTES_PER_CHUNK || +#else + if (mtd->oobblock < YAFFS_BYTES_PER_CHUNK || +#endif mtd->oobsize != YAFFS_BYTES_PER_SPARE) { T(YAFFS_TRACE_ALWAYS, ("yaffs: MTD device does not support have the " @@ -1594,8 +1653,13 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, dev->queryNANDBlock = nandmtd2_QueryNANDBlock; dev->spareBuffer = YMALLOC(mtd->oobsize); dev->isYaffs2 = 1; +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + dev->nBytesPerChunk = mtd->writesize; + dev->nChunksPerBlock = mtd->erasesize / mtd->writesize; +#else dev->nBytesPerChunk = mtd->oobblock; dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock; +#endif nBlocks = mtd->size / mtd->erasesize; dev->nCheckpointReservedBlocks = 10; @@ -1675,6 +1739,16 @@ static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data, return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL; } +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +static int yaffs_read_super(struct file_system_type *fs, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) +{ + + return get_sb_bdev(fs, flags, dev_name, data, + yaffs_internal_read_super_mtd, mnt); +} +#else static struct super_block *yaffs_read_super(struct file_system_type *fs, int flags, const char *dev_name, void *data) @@ -1683,6 +1757,7 @@ static struct super_block *yaffs_read_super(struct file_system_type *fs, return get_sb_bdev(fs, flags, dev_name, data, yaffs_internal_read_super_mtd); } +#endif static struct file_system_type yaffs_fs_type = { .owner = THIS_MODULE, @@ -1712,6 +1787,15 @@ static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data, return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL; } +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +static int yaffs2_read_super(struct file_system_type *fs, + int flags, const char *dev_name, void *data, + struct vfsmount *mnt) +{ + return get_sb_bdev(fs, flags, dev_name, data, + yaffs2_internal_read_super_mtd, mnt); +} +#else static struct super_block *yaffs2_read_super(struct file_system_type *fs, int flags, const char *dev_name, void *data) @@ -1720,6 +1804,7 @@ static struct super_block *yaffs2_read_super(struct file_system_type *fs, return get_sb_bdev(fs, flags, dev_name, data, yaffs2_internal_read_super_mtd); } +#endif static struct file_system_type yaffs2_fs_type = { .owner = THIS_MODULE, diff --git a/yaffs_mtdif.c b/yaffs_mtdif.c index 7dbf07a..1f40e8f 100644 --- a/yaffs_mtdif.c +++ b/yaffs_mtdif.c @@ -14,7 +14,7 @@ */ const char *yaffs_mtdif_c_version = - "$Id: yaffs_mtdif.c,v 1.13 2005-11-07 07:13:33 charles Exp $"; + "$Id: yaffs_mtdif.c,v 1.14 2006-09-26 13:28:13 vwool Exp $"; #include "yportenv.h" @@ -26,6 +26,7 @@ const char *yaffs_mtdif_c_version = #include "linux/time.h" #include "linux/mtd/nand.h" +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) static struct nand_oobinfo yaffs_oobinfo = { .useecc = 1, .eccbytes = 6, @@ -35,16 +36,74 @@ static struct nand_oobinfo yaffs_oobinfo = { static struct nand_oobinfo yaffs_noeccinfo = { .useecc = 0, }; +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob) +{ + oob[0] = spare->tagByte0; + oob[1] = spare->tagByte1; + oob[2] = spare->tagByte2; + oob[3] = spare->tagByte3; + oob[4] = spare->tagByte4; + oob[5] = spare->tagByte5 & 0x3f; + oob[5] |= spare->blockStatus == 'Y' ? 0: 0x80; + oob[5] |= spare->pageStatus == 0 ? 0: 0x40; + oob[6] = spare->tagByte6; + oob[7] = spare->tagByte7; +} + +static inline void translate_oob2spare(yaffs_Spare *spare, __u8 *oob) +{ + struct yaffs_NANDSpare *nspare = (struct yaffs_NANDSpare *)spare; + spare->tagByte0 = oob[0]; + spare->tagByte1 = oob[1]; + spare->tagByte2 = oob[2]; + spare->tagByte3 = oob[3]; + spare->tagByte4 = oob[4]; + spare->tagByte5 = oob[5] == 0xff ? 0xff : oob[5] & 0x3f; + spare->blockStatus = oob[5] & 0x80 ? 0xff : 'Y'; + spare->pageStatus = oob[5] & 0x40 ? 0xff : 0; + spare->tagByte6 = oob[6]; + spare->tagByte7 = oob[7]; + + nspare->eccres1 = nspare->eccres2 = 0; /* FIXME */ +} +#endif int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND, const __u8 * data, const yaffs_Spare * spare) { struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + struct mtd_oob_ops ops; +#endif size_t dummy; int retval = 0; loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk; - +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + __u8 spareAsBytes[8]; /* OOB */ + + if (data && !spare) + retval = mtd->write(mtd, addr, dev->nBytesPerChunk, + &dummy, data); + else if (spare) { + if (dev->useNANDECC) { + translate_spare2oob(spare, spareAsBytes); + ops.mode = MTD_OOB_AUTO; + ops.ooblen = 8; /* temp hack */ + } else { + ops.mode = MTD_OOB_RAW; + ops.ooblen = YAFFS_BYTES_PER_SPARE; + } + ops.len = data ? dev->nBytesPerChunk : ops.ooblen; + ops.datbuf = (u8 *)data; + ops.ooboffs = 0; + ops.oobbuf = spareAsBytes; + retval = mtd->write_oob(mtd, addr, &ops); + } +#else __u8 *spareAsBytes = (__u8 *) spare; if (data && spare) { @@ -68,6 +127,7 @@ int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND, mtd->write_oob(mtd, addr, YAFFS_BYTES_PER_SPARE, &dummy, spareAsBytes); } +#endif if (retval == 0) return YAFFS_OK; @@ -79,11 +139,36 @@ int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data, yaffs_Spare * spare) { struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + struct mtd_oob_ops ops; +#endif size_t dummy; int retval = 0; loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk; - +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + __u8 spareAsBytes[8]; /* OOB */ + + if (data && !spare) + retval = mtd->read(mtd, addr, dev->nBytesPerChunk, + &dummy, data); + else if (spare) { + if (dev->useNANDECC) { + ops.mode = MTD_OOB_AUTO; + ops.ooblen = 8; /* temp hack */ + } else { + ops.mode = MTD_OOB_RAW; + ops.ooblen = YAFFS_BYTES_PER_SPARE; + } + ops.len = data ? dev->nBytesPerChunk : ops.ooblen; + ops.datbuf = data; + ops.ooboffs = 0; + ops.oobbuf = spareAsBytes; + retval = mtd->read_oob(mtd, addr, &ops); + if (dev->useNANDECC) + translate_oob2spare(spare, spareAsBytes); + } +#else __u8 *spareAsBytes = (__u8 *) spare; if (data && spare) { @@ -112,6 +197,7 @@ int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data, mtd->read_oob(mtd, addr, YAFFS_BYTES_PER_SPARE, &dummy, spareAsBytes); } +#endif if (retval == 0) return YAFFS_OK; diff --git a/yaffs_mtdif2.c b/yaffs_mtdif2.c index 1b917be..b7c973e 100644 --- a/yaffs_mtdif2.c +++ b/yaffs_mtdif2.c @@ -16,7 +16,7 @@ /* mtd interface for YAFFS2 */ const char *yaffs_mtdif2_c_version = - "$Id: yaffs_mtdif2.c,v 1.12 2006-09-21 08:13:59 charles Exp $"; + "$Id: yaffs_mtdif2.c,v 1.13 2006-09-26 13:28:13 vwool Exp $"; #include "yportenv.h" @@ -34,7 +34,11 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, const yaffs_ExtendedTags * tags) { struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + struct mtd_oob_ops ops; +#else size_t dummy; +#endif int retval = 0; loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk; @@ -46,6 +50,23 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p" TENDSTR), chunkInNAND, data, tags)); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + if (tags) + yaffs_PackTags2(&pt, tags); + else + BUG(); /* both tags and data should always be present */ + + if (data) { + ops.mode = MTD_OOB_AUTO; + ops.ooblen = sizeof(pt); + ops.len = dev->nBytesPerChunk; + ops.ooboffs = 0; + ops.datbuf = (__u8 *)data; + ops.oobbuf = (void *)&pt; + retval = mtd->write_oob(mtd, addr, &ops); + } else + BUG(); /* both tags and data should always be present */ +#else if (tags) { yaffs_PackTags2(&pt, tags); } @@ -70,6 +91,7 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, (__u8 *) & pt); } +#endif if (retval == 0) return YAFFS_OK; @@ -81,6 +103,9 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data, yaffs_ExtendedTags * tags) { struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + struct mtd_oob_ops ops; +#endif size_t dummy; int retval = 0; @@ -93,6 +118,20 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p" TENDSTR), chunkInNAND, data, tags)); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + if (data && !tags) + retval = mtd->read(mtd, addr, dev->nBytesPerChunk, + &dummy, data); + else if (tags) { + ops.mode = MTD_OOB_AUTO; + ops.ooblen = sizeof(pt); + ops.len = data ? dev->nBytesPerChunk : sizeof(pt); + ops.ooboffs = 0; + ops.datbuf = data; + ops.oobbuf = dev->spareBuffer; + retval = mtd->read_oob(mtd, addr, &ops); + } +#else if (data && tags) { if (dev->useNANDECC) { retval = @@ -115,6 +154,7 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, mtd->read_oob(mtd, addr, mtd->oobsize, &dummy, dev->spareBuffer); } +#endif memcpy(&pt, dev->spareBuffer, sizeof(pt)); -- 2.30.2