From 00057626901725d0b64045f6823d67edae691e00 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Thu, 1 Nov 2012 11:07:23 +0000
Subject: [PATCH] generic: make yaffs work on 3.6

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>

SVN-Revision: 34054
---
 ...add-underscore-to-mtd-internal-names.patch |  72 +++++++
 .../510-yaffs-3.4-use-d_make_root.patch       |  14 ++
 .../511-yaffs-3.5-use-clear_inode.patch       |  15 ++
 .../512-yaffs-3.6-fix-dir_inode-ops.patch     |  60 ++++++
 ...-delayed-work-instead-of-write_super.patch | 180 ++++++++++++++++++
 5 files changed, 341 insertions(+)
 create mode 100644 target/linux/generic/patches-3.6/509-yaffs-3.4-add-underscore-to-mtd-internal-names.patch
 create mode 100644 target/linux/generic/patches-3.6/510-yaffs-3.4-use-d_make_root.patch
 create mode 100644 target/linux/generic/patches-3.6/511-yaffs-3.5-use-clear_inode.patch
 create mode 100644 target/linux/generic/patches-3.6/512-yaffs-3.6-fix-dir_inode-ops.patch
 create mode 100644 target/linux/generic/patches-3.6/513-yaffs-3.6-use-delayed-work-instead-of-write_super.patch

diff --git a/target/linux/generic/patches-3.6/509-yaffs-3.4-add-underscore-to-mtd-internal-names.patch b/target/linux/generic/patches-3.6/509-yaffs-3.4-add-underscore-to-mtd-internal-names.patch
new file mode 100644
index 0000000000..14f342da80
--- /dev/null
+++ b/target/linux/generic/patches-3.6/509-yaffs-3.4-add-underscore-to-mtd-internal-names.patch
@@ -0,0 +1,72 @@
+--- a/fs/yaffs2/yaffs_vfs_glue.c
++++ b/fs/yaffs2/yaffs_vfs_glue.c
+@@ -2793,6 +2793,15 @@ static struct super_block *yaffs_interna
+ 		return NULL;
+ 	}
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
++	T(YAFFS_TRACE_OS, (TSTR(" erase %p\n"), mtd->_erase));
++	T(YAFFS_TRACE_OS, (TSTR(" read %p\n"), mtd->_read));
++	T(YAFFS_TRACE_OS, (TSTR(" write %p\n"), mtd->_write));
++	T(YAFFS_TRACE_OS, (TSTR(" readoob %p\n"), mtd->_read_oob));
++	T(YAFFS_TRACE_OS, (TSTR(" writeoob %p\n"), mtd->_write_oob));
++	T(YAFFS_TRACE_OS, (TSTR(" block_isbad %p\n"), mtd->_block_isbad));
++	T(YAFFS_TRACE_OS, (TSTR(" block_markbad %p\n"), mtd->_block_markbad));
++#else
+ 	T(YAFFS_TRACE_OS, (TSTR(" erase %p\n"), mtd->erase));
+ 	T(YAFFS_TRACE_OS, (TSTR(" read %p\n"), mtd->read));
+ 	T(YAFFS_TRACE_OS, (TSTR(" write %p\n"), mtd->write));
+@@ -2800,6 +2809,7 @@ static struct super_block *yaffs_interna
+ 	T(YAFFS_TRACE_OS, (TSTR(" writeoob %p\n"), mtd->write_oob));
+ 	T(YAFFS_TRACE_OS, (TSTR(" block_isbad %p\n"), mtd->block_isbad));
+ 	T(YAFFS_TRACE_OS, (TSTR(" block_markbad %p\n"), mtd->block_markbad));
++#endif
+ 	T(YAFFS_TRACE_OS, (TSTR(" %s %d\n"), WRITE_SIZE_STR, WRITE_SIZE(mtd)));
+ 	T(YAFFS_TRACE_OS, (TSTR(" oobsize %d\n"), mtd->oobsize));
+ 	T(YAFFS_TRACE_OS, (TSTR(" erasesize %d\n"), mtd->erasesize));
+@@ -2828,6 +2838,15 @@ static struct super_block *yaffs_interna
+ 
+ 	if (yaffs_version == 2) {
+ 		/* Check for version 2 style functions */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
++		if (!mtd->_erase ||
++		    !mtd->_block_isbad ||
++		    !mtd->_block_markbad ||
++		    !mtd->_read ||
++		    !mtd->_write ||
++		    !mtd->_read_oob ||
++		    !mtd->_write_oob) {
++#else
+ 		if (!mtd->erase ||
+ 		    !mtd->block_isbad ||
+ 		    !mtd->block_markbad ||
+@@ -2839,6 +2858,7 @@ static struct super_block *yaffs_interna
+ 		    !mtd->write_ecc ||
+ 		    !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) {
+ #endif
++#endif
+ 			T(YAFFS_TRACE_ALWAYS,
+ 			  (TSTR("yaffs: MTD device does not support required "
+ 			   "functions\n")));
+@@ -2855,6 +2875,13 @@ static struct super_block *yaffs_interna
+ 		}
+ 	} else {
+ 		/* Check for V1 style functions */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
++		if (!mtd->_erase ||
++		    !mtd->_read ||
++		    !mtd->_write ||
++		    !mtd->_read_oob ||
++		    !mtd->_write_oob) {
++#else
+ 		if (!mtd->erase ||
+ 		    !mtd->read ||
+ 		    !mtd->write ||
+@@ -2864,6 +2891,7 @@ static struct super_block *yaffs_interna
+ 		    !mtd->write_ecc ||
+ 		    !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) {
+ #endif
++#endif
+ 			T(YAFFS_TRACE_ALWAYS,
+ 			  (TSTR("yaffs: MTD device does not support required "
+ 			   "functions\n")));
diff --git a/target/linux/generic/patches-3.6/510-yaffs-3.4-use-d_make_root.patch b/target/linux/generic/patches-3.6/510-yaffs-3.4-use-d_make_root.patch
new file mode 100644
index 0000000000..0ef59d606e
--- /dev/null
+++ b/target/linux/generic/patches-3.6/510-yaffs-3.4-use-d_make_root.patch
@@ -0,0 +1,14 @@
+--- a/fs/yaffs2/yaffs_vfs_glue.c
++++ b/fs/yaffs2/yaffs_vfs_glue.c
+@@ -3119,7 +3119,11 @@ static struct super_block *yaffs_interna
+ 
+ 	T(YAFFS_TRACE_OS, (TSTR("yaffs_read_super: got root inode\n")));
+ 
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
++	root = d_make_root(inode);
++#else
+ 	root = d_alloc_root(inode);
++#endif
+ 
+ 	T(YAFFS_TRACE_OS, (TSTR("yaffs_read_super: d_alloc_root done\n")));
+ 
diff --git a/target/linux/generic/patches-3.6/511-yaffs-3.5-use-clear_inode.patch b/target/linux/generic/patches-3.6/511-yaffs-3.5-use-clear_inode.patch
new file mode 100644
index 0000000000..f4479675a2
--- /dev/null
+++ b/target/linux/generic/patches-3.6/511-yaffs-3.5-use-clear_inode.patch
@@ -0,0 +1,15 @@
+--- a/fs/yaffs2/yaffs_vfs_glue.c
++++ b/fs/yaffs2/yaffs_vfs_glue.c
+@@ -924,7 +924,11 @@ static void yaffs_evict_inode( struct in
+ 	if (!inode->i_nlink && !is_bad_inode(inode))
+ 		deleteme = 1;
+ 	truncate_inode_pages(&inode->i_data,0);
+-	end_writeback(inode);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
++	clear_inode(inode);
++#else
++ 	end_writeback(inode);
++#endif
+ 
+ 	if(deleteme && obj){
+ 		dev = obj->my_dev;
diff --git a/target/linux/generic/patches-3.6/512-yaffs-3.6-fix-dir_inode-ops.patch b/target/linux/generic/patches-3.6/512-yaffs-3.6-fix-dir_inode-ops.patch
new file mode 100644
index 0000000000..f9db0b3fab
--- /dev/null
+++ b/target/linux/generic/patches-3.6/512-yaffs-3.6-fix-dir_inode-ops.patch
@@ -0,0 +1,60 @@
+--- a/fs/yaffs2/yaffs_vfs_glue.c
++++ b/fs/yaffs2/yaffs_vfs_glue.c
+@@ -272,20 +272,29 @@ static int yaffs_sync_object(struct file
+ 
+ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir);
+ 
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
++static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
++			bool excl);
++#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+ static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ 			struct nameidata *n);
+-#else
++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+ static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,
+ 			struct nameidata *n);
++#else
++static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode);
+ #endif
++
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
++static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
++					unsigned int flags);
++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
+ 					struct nameidata *n);
+ #else
+-static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode);
+ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry);
+ #endif
++
+ static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
+ 			struct dentry *dentry);
+ static int yaffs_unlink(struct inode *dir, struct dentry *dentry);
+@@ -811,7 +820,10 @@ struct inode *yaffs_get_inode(struct sup
+ /*
+  * Lookup is used to find objects in the fs
+  */
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
++static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
++				   unsigned int flags)
++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+ 
+ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
+ 				struct nameidata *n)
+@@ -1801,7 +1813,10 @@ static int yaffs_mkdir(struct inode *dir
+ 	return retVal;
+ }
+ 
+-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
++static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
++			bool excl)
++#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+ static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ 			struct nameidata *n)
+ #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
diff --git a/target/linux/generic/patches-3.6/513-yaffs-3.6-use-delayed-work-instead-of-write_super.patch b/target/linux/generic/patches-3.6/513-yaffs-3.6-use-delayed-work-instead-of-write_super.patch
new file mode 100644
index 0000000000..579932c69e
--- /dev/null
+++ b/target/linux/generic/patches-3.6/513-yaffs-3.6-use-delayed-work-instead-of-write_super.patch
@@ -0,0 +1,180 @@
+--- a/fs/yaffs2/yaffs_vfs_glue.c
++++ b/fs/yaffs2/yaffs_vfs_glue.c
+@@ -394,6 +394,84 @@ static void yaffs_touch_super(yaffs_dev_
+ static int yaffs_vfs_setattr(struct inode *, struct iattr *);
+ 
+ 
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
++
++#define yaffs_super_to_dev(sb)    ((struct yaffs_dev_s *)sb->s_fs_info)
++
++static inline struct yaffs_LinuxContext *
++yaffs_sb_to_ylc(struct super_block *sb)
++{
++	struct yaffs_dev_s *ydev;
++	struct yaffs_LinuxContext *ylc;
++
++	ydev = yaffs_super_to_dev(sb);
++	ylc = yaffs_dev_to_lc(ydev);
++	return ylc;
++}
++
++static inline struct super_block *yaffs_work_to_sb(struct work_struct *work)
++{
++	struct delayed_work *dwork;
++	struct yaffs_LinuxContext *ylc;
++
++	dwork = container_of(work, struct delayed_work, work);
++	ylc = container_of(dwork, struct yaffs_LinuxContext, sb_sync_dwork);
++	return ylc->superBlock;
++}
++
++static void yaffs_sb_sync_dwork_func(struct work_struct *work)
++{
++	struct super_block *sb = yaffs_work_to_sb(work);
++
++	yaffs_write_super(sb);
++}
++
++static void yaffs_init_sb_sync_dwork(struct yaffs_LinuxContext *ylc)
++{
++	INIT_DELAYED_WORK(&ylc->sb_sync_dwork, yaffs_sb_sync_dwork_func);
++}
++
++static void yaffs_cancel_sb_sync_dwork(struct super_block *sb)
++{
++	struct yaffs_LinuxContext *ylc = yaffs_sb_to_ylc(sb);
++
++	cancel_delayed_work_sync(&ylc->sb_sync_dwork);
++}
++
++static inline bool yaffs_sb_is_dirty(struct super_block *sb)
++{
++	struct yaffs_LinuxContext *ylc = yaffs_sb_to_ylc(sb);
++
++	return !!ylc->sb_dirty;
++}
++
++static inline void yaffs_sb_set_dirty(struct super_block *sb, int dirty)
++{
++	struct yaffs_LinuxContext *ylc = yaffs_sb_to_ylc(sb);
++
++	if (ylc->sb_dirty == dirty)
++		return;
++
++	ylc->sb_dirty = dirty;
++	if (dirty)
++		queue_delayed_work(system_long_wq, &ylc->sb_sync_dwork,
++				   msecs_to_jiffies(5000));
++}
++#else
++static inline bool yaffs_sb_is_dirty(struct super_block *sb)
++{
++	return !!sb->s_dirt;
++}
++
++static inline void yaffs_sb_set_dirty(struct super_block *sb, int dirty)
++{
++	sb->s_dirt = dirty;
++}
++
++static inline void yaffs_init_sb_sync_dwork(struct yaffs_LinuxContext *ylc) {}
++static inline void yaffs_cancel_sb_sync_dwork(struct super_block *sb) {}
++#endif /* >= 3.6.0 */
++
+ static struct address_space_operations yaffs_file_address_operations = {
+ 	.readpage = yaffs_readpage,
+ 	.writepage = yaffs_writepage,
+@@ -527,7 +605,9 @@ static const struct super_operations yaf
+ 	.clear_inode = yaffs_clear_inode,
+ #endif
+ 	.sync_fs = yaffs_sync_fs,
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
+ 	.write_super = yaffs_write_super,
++#endif
+ };
+ 
+ 
+@@ -2314,7 +2394,7 @@ static int yaffs_do_sync_fs(struct super
+ 	T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
+ 		(TSTR("yaffs_do_sync_fs: gc-urgency %d %s %s%s\n"),
+ 		gc_urgent,
+-		sb->s_dirt ? "dirty" : "clean",
++		yaffs_sb_is_dirty(sb) ? "dirty" : "clean",
+ 		request_checkpoint ? "checkpoint requested" : "no checkpoint",
+ 		oneshot_checkpoint ? " one-shot" : "" ));
+ 
+@@ -2323,9 +2403,9 @@ static int yaffs_do_sync_fs(struct super
+ 			oneshot_checkpoint) &&
+ 			!dev->is_checkpointed;
+ 
+-	if (sb->s_dirt || do_checkpoint) {
++	if (yaffs_sb_is_dirty(sb) || do_checkpoint) {
+ 		yaffs_flush_super(sb, !dev->is_checkpointed && do_checkpoint);
+-		sb->s_dirt = 0;
++		yaffs_sb_set_dirty(sb, 0);
+ 		if(oneshot_checkpoint)
+ 			yaffs_auto_checkpoint &= ~4;
+ 	}
+@@ -2601,6 +2681,8 @@ static void yaffs_put_super(struct super
+ 
+ 	yaffs_flush_super(sb,1);
+ 
++	yaffs_cancel_sb_sync_dwork(sb);
++
+ 	if (yaffs_dev_to_lc(dev)->putSuperFunc)
+ 		yaffs_dev_to_lc(dev)->putSuperFunc(sb);
+ 
+@@ -2639,7 +2721,7 @@ static void yaffs_touch_super(yaffs_dev_
+ 
+ 	T(YAFFS_TRACE_OS, (TSTR("yaffs_touch_super() sb = %p\n"), sb));
+ 	if (sb)
+-		sb->s_dirt = 1;
++		yaffs_sb_set_dirty(sb, 1);
+ }
+ 
+ typedef struct {
+@@ -2965,6 +3047,8 @@ static struct super_block *yaffs_interna
+ 	context->dev = dev;
+ 	context->superBlock = sb;
+ 
++	yaffs_init_sb_sync_dwork(context);
++
+ 	dev->read_only = read_only;
+ 
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+@@ -3151,7 +3235,7 @@ static struct super_block *yaffs_interna
+ 		return NULL;
+ 	}
+ 	sb->s_root = root;
+-	sb->s_dirt = !dev->is_checkpointed;
++	yaffs_sb_set_dirty(sb, !dev->is_checkpointed);
+ 	T(YAFFS_TRACE_ALWAYS,
+ 		(TSTR("yaffs_read_super: is_checkpointed %d\n"),
+ 		dev->is_checkpointed));
+--- a/fs/yaffs2/yaffs_linux.h
++++ b/fs/yaffs2/yaffs_linux.h
+@@ -34,6 +34,11 @@ struct yaffs_LinuxContext {
+ 
+ 	struct task_struct *readdirProcess;
+ 	unsigned mount_id;
++
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
++	struct delayed_work sb_sync_dwork;	/* superblock write-out work */
++	int sb_dirty;				/* superblock is dirty */
++#endif
+ };
+ 
+ #define yaffs_dev_to_lc(dev) ((struct yaffs_LinuxContext *)((dev)->os_context))
+--- a/fs/yaffs2/yportenv.h
++++ b/fs/yaffs2/yportenv.h
+@@ -49,6 +49,9 @@
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
+ #include <linux/xattr.h>
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
++#include <linux/workqueue.h>
++#endif
+ 
+ #define YCHAR char
+ #define YUCHAR unsigned char
-- 
GitLab