Interworking with 2.6.18 kernel enabled
authorvwool <vwool>
Tue, 26 Sep 2006 13:28:13 +0000 (13:28 +0000)
committervwool <vwool>
Tue, 26 Sep 2006 13:28:13 +0000 (13:28 +0000)
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
yaffs_mtdif.c
yaffs_mtdif2.c

index d90e291..30ac265 100644 (file)
@@ -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 <linux/config.h>
@@ -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,
index 7dbf07a..1f40e8f 100644 (file)
@@ -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;
index 1b917be..b7c973e 100644 (file)
@@ -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));